Repository navigation
Integrations HotChocolate GraphQL
Seamlessly integrate FxMap with HotChocolate GraphQL to automatically map data in your GraphQL resolvers.
HotChocolate is a powerful GraphQL server for .NET. When combined with FxMap, you can:
Use FxMap profiles for your GraphQL types to automatically fetch and map data from multiple services.
GraphQL queries can seamlessly fetch data across multiple microservices without complex resolver logic.
Eliminate boilerplate mapping code in your resolvers - FxMap handles it all declaratively.
dotnet add package FxMap
dotnet add package FxMap.HotChocolateOr via Package Manager Console:
Install-Package FxMap
Install-Package FxMap.HotChocolateSet up HotChocolate first, then register FxMap with the HotChocolate integration:
using FxMap;
using HotChocolate;
var builder = WebApplication.CreateBuilder(args);
// 1. Configure HotChocolate GraphQL Server
var registerBuilder = builder.Services.AddGraphQLServer()
.AddQueryType<Query>()
.AddType<MembersType>();
// 2. Configure FxMap with HotChocolate integration
builder.Services.AddFxMap(cfg =>
{
cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
cfg.AddGrpcClients(c =>
c.AddGrpcHosts("http://localhost:5001", "http://localhost:5002", "http://localhost:5003"));
cfg.SetRetryPolicy(3, n => n * TimeSpan.FromSeconds(2),
(e, ts) => Console.WriteLine($"Error: {e.Message}"));
})
.AddEntityFrameworkCore(cfg => cfg.AddDbContexts(typeof(Service1Context), typeof(OtherService1Context)))
.AddMongoDb(cfg => cfg.AddCollection(memberSocialCollection))
.AddHotChocolate(cfg => cfg.AddRequestExecutorBuilder(registerBuilder));
var app = builder.Build();
app.MapGraphQL();
app.Run();Key Point: Pass the HotChocolate request executor builder to FxMap using .AddHotChocolate(). This enables FxMap to automatically resolve dependencies in your GraphQL queries.
FxMap automatically detects and resolves dependencies in your GraphQL types. When a property depends on another FxMap-mapped property, FxMap resolves them in the correct order:
// GraphQL response type
public class MemberResponse
{
public string Id { get; set; }
public string UserId { get; set; }
public string ProvinceId { get; set; } // populated first
public string CountryName { get; set; } // populated second (depends on ProvinceId)
}
// One profile holds both rules
public class MemberResponseProfile : ProfileOf<MemberResponse>
{
protected override void Configure()
{
// fetch ProvinceId from the User service
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
.For(x => x.ProvinceId, "ProvinceId");
// fetch CountryName from the Province service
// FxMap resolves ProvinceId (the rule above) before executing this
UseDistributedKey<ProvinceDistributedKey>()
.Of(x => x.ProvinceId)
.For(x => x.CountryName, "Country.Name");
}
}1
GraphQL query requests countryName
2
FxMap detects that CountryName depends on ProvinceId
3
Resolves ProvinceId from User service first
4
Uses the resolved ProvinceId to fetch CountryName from Province service
The client does not have to select provinceId. See dependent properties for the full pattern.
Your resolvers become incredibly simple - just return your data. FxMap handles ALL the mapping automatically:
public class Query
{
public List<MemberResponse> GetMembers([Parameters] GetMembersParameters parameters)
{
// Just return your data - FxMap handles everything!
return
[
.. Enumerable.Range(1, 3).Select(a => new MemberResponse
{
Id = a.ToString(),
UserId = a.ToString(),
MemberAdditionalId = a.ToString(),
MemberSocialId = a.ToString(),
MemberAddressId = a.ToString()
})
];
}
}✨
Notice there's NO manual mapping, NO service injection, NO MapDataAsync calls. FxMap automatically intercepts the HotChocolate resolver and maps all profile-declared properties before returning to the GraphQL client.
Query only the fields you need. FxMap automatically resolves dependencies:
{
members {
id
countryName
}
}Only requesting countryName
// FxMap automatically:
// 1. Fetches ProvinceId
// from User service
// 2. Uses ProvinceId to fetch
// Country.Name from
// Province service
// 3. Returns only countryName
// to GraphQL client✓ Dependencies resolved automatically
{
"data": {
"members": [
{
"id": "member-1",
"countryName": "Canada"
},
{
"id": "member-2",
"countryName": "United States"
}
]
}
}You can also use FxMap in field resolvers for more granular control:
// UserLookup DTO and profile
public class UserLookup
{
public string UserId { get; set; }
public UserDto? User { get; set; }
}
public class UserLookupProfile : ProfileOf<UserLookup>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
.For(x => x.User, "{ Id, Name, Email }");
}
}
// Use in HotChocolate's resolver pattern
public class OrderResolvers
{
public async Task<UserDto?> GetUser(
[Parent] OrderType order,
[Service] IDistributedMapper mapper)
{
var result = new UserLookup { UserId = order.UserId };
await mapper.MapDataAsync(result);
return result.User;
}
}When mapping multiple orders, FxMap automatically batches requests to remote services. Instead of N+1 queries, you get efficient batch requests.
FxMap caches entities within the same request, preventing duplicate fetches even across different resolvers.
FxMap expressions are compiled at startup, ensuring blazing-fast runtime performance for GraphQL queries.
FxMap works seamlessly with HotChocolate's DataLoader for even better performance:
// UserLookup DTO and profile (can be reused across resolvers)
public class UserLookup
{
public string UserId { get; set; }
public UserDto? User { get; set; }
}
public class UserLookupProfile : ProfileOf<UserLookup>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
.For(x => x.User, "{ Id, Name, Email }");
}
}
public class UserDataLoader : BatchDataLoader<string, UserDto>
{
private readonly IDistributedMapper _mapper;
public UserDataLoader(
IDistributedMapper mapper,
IBatchScheduler batchScheduler,
DataLoaderOptions options = null)
: base(batchScheduler, options)
{
_mapper = mapper;
}
protected override async Task<IReadOnlyDictionary<string, UserDto>> LoadBatchAsync(
IReadOnlyList<string> keys,
CancellationToken cancellationToken)
{
var lookups = keys.Select(id => new UserLookup { UserId = id }).ToList();
// FxMap batches all user fetches efficiently
await _mapper.MapDataAsync(lookups);
return lookups.ToDictionary(
l => l.UserId,
l => l.User!
);
}
}Use FxMap expressions to only fetch the fields your GraphQL query actually requests. This prevents over-fetching and improves performance.
Source: https://fxmapper.net/docs/integrations/hotchocolate/ — the website is always the most up to date version.
Introduction
Getting Started
Configuration
- Service Registration
- Entities & Profiles
- Handlers
- Pipelines
- Strongly Typed IDs
- Error Handling
- Retry Policy
- Supervisor
- Telemetry
- Kestrel (HTTP/2)
- Analyzers
Expressions
- Overview
- Property Access
- Filters, Sorting & Paging
- Functions
- Aggregations
- Projections
- Coalesce & Ternary
- GroupBy
Data Providers
Transports
Integrations
Quality
AI Assistants
Migration
Release Notes