Repository navigation
Releases: EntityGraphQL/EntityGraphQL
Release list
6.0.0-beta6
Breaking Changes
- #515 -
DefaultGraphQLResponseSerializerandDefaultGraphQLRequestDeserializerdefaultJsonSerializerOptionsnow useJsonSerializerDefaults.Web. For the request deserializer this enables case-insensitive property matching and reading numbers from JSON strings. The response serializer's output is unchanged (it was already camelCase). ExecutionOptions.MaxQueryNodesrenamed toMaxFieldSelections— it counts field selections (the GraphQL spec term) after fragment expansion, not AST or result nodes.ExecutionOptions.UserKeySelectorrenamed toRateLimitUserKeySelectorto reflect that it only affects per-field rate limiters taggeduserSpecific: true.
6.0.0-beta5
Breaking Changes
AddGraphQLOptions<TContext>now exposes overloadedConfigureSchema(...)methods instead of settable schema-configuration delegate properties. Useoptions.ConfigureSchema(schema => { ... })for the common case, oroptions.ConfigureSchema((schema, services) => { ... })when schema setup needs the activeIServiceProvider.AddGraphQLSchema()inEntityGraphQL.AspNetnow returns a dedicatedGraphQLSchemaBuilder<TContext>instead ofIServiceCollection. Schema-shape customization should now be chained withConfigureGraphQLSchema(...), for example:services.AddGraphQLSchema<MyContext>(options => { ... }).ConfigureGraphQLSchema<MyContext>(schema => { ... });
Changes
- #508 - Added a
src/examples/toolingexample showing GraphiQL and Hot Chocolate Nitro hosted against anEntityGraphQL.AspNet/api/graphqlendpoint. - Query/document errors now preserve structured source locations in addition to the existing message text, and
GraphQLErrorresponses now emitlocationsmetadata when available. Also normalized invalid field-directive registration to throwEntityGraphQLSchemaExceptioninstead ofInvalidOperationExceptionon the public schema API surface. - #515 - The
MapGraphQLendpoint no longer silently swallows exceptions. Response execution/serialization failures (HTTP 500) are now logged atErrorand request rejections (406/415/400, including request-body deserialization failures) are logged atDebugvia the standardILoggerinfrastructure, so serialization issues like graph-cycle exceptions fromRuntimeTypeJsonConverterare diagnosable. TheSchemaProvider<TContext>logger is now wired up from DI inEntityGraphQL.AspNet, so query execution errors are logged as well. - #515 -
DefaultGraphQLResponseSerializernow exposes its defaultJsonSerializerOptionsvia the staticDefaultGraphQLResponseSerializer.CreateDefaultOptions(), so the defaults can be tweaked (e.g. removingRuntimeTypeJsonConverter) without reproducing every setting by hand. The default options now also useJsonSerializerDefaults.Web.
Full Changelog: 6.0.0-beta4...6.0.0-beta5
6.0.0-beta4
Breaking Changes
- Simplified
IFieldExtensioncompilation hooks by replacing long positional parameter lists with context objects:GetExpressionAndArguments()now takesFieldExtensionExpressionContextProcessExpressionPreSelection()now takesFieldExtensionPreSelectionContextProcessExpressionSelection()now takesFieldExtensionSelectionContext
Changes
- #513 -
AddGraphQLSchema()now supports configuring the registeredSchemaProvider<TContext>lifetime viaAddGraphQLOptions.SchemaLifetime. The default remains singleton, with scoped/transient lifetimes available for request-specific schema construction.
Fixes
- #498 - fix ExecutableDirectiveLocation naming regression introduced in beta3
6.0.0-beta3
Breaking Changes
- Fields in
ExecutableDirectiveLocationenum have been renamed in C# style - #476 - Introduce generic custom type converters (from-to, to-only, from-only) for flexible runtime value conversion.
- Expand
isAnyto support additional types through the method provider - Removes
ICustomTypeConverter. See updated docs and the more flexible converting methods available
- Expand
- Renamed
SchemaBuilderSchemaOptionstoSchemaProviderOptionsfor better clarity between schema builder reflection options and schema provider configuration options AddGraphQLOptions<TSchemaContext>refactored from inheritance to composition:- Now exposes
Builderproperty forSchemaBuilderOptions(controls building/reflection behavior) - Now exposes
Schemaproperty forSchemaProviderOptions(controls schema provider configuration like authorization, introspection, error handling, field naming) - Removed
FieldNamerproperty - now accessed viaoptions.Schema.FieldNamer PreBuildSchemaFromContextmoved fromSchemaProviderOptionstoSchemaBuilderOptions- now accessed viaoptions.Builder.PreBuildSchemaFromContext(it's called during the schema building phase, not runtime)
- Now exposes
- Removed
introspectionEnabledparameter fromAddGraphQLSchemaextension method - configure viaoptions.Schema.IntrospectionEnabledinstead - Authorization refactoring:
RequiredAuthorizationnow uses a keyed data structure for extensibilityRequiredAuthorizationno longer has separateRolesbacking field - roles are stored via"egql:core:roles"key inKeyedDatadictionary- The
Rolesproperty is now nullable and computed from keyed data - Policy support moved entirely to
EntityGraphQL.AspNetpackage using"egql:aspnet:policies"key RequiredAuthorizationconstructor that took roles parameter has been removed - useRequiresAnyRole()orRequiresAllRoles()methods instead- Custom authorization implementations should use namespaced keys (e.g.,
"myapp:custom-auth") to avoid conflicts
- Added
withoutServiceFieldsparameter toIFieldExtension.GetExpressionAndArguments()to allow extensions to know when they're in the first pass of two-pass execution and should skip service-dependent expressions.
Changes
- Added pre-execution query guards (
MaxQueryDepth,MaxQueryNodes,MaxFieldAliases,MaxQueryComplexity) toExecutionOptions. All default to unlimited (opt-in). A limit violation returns a GraphQLDocumentErrorand prevents any resolver from running. Configure inExecutionOptionsin your call toschema.ExecuteRequest(...). - Added complexity scoring via
field.SetComplexity(int)(fixed cost) orfield.SetComplexity(ctx => ctx.Args.take * (1 + ctx.ChildComplexity))(args-aware). Pluggable viaIQueryComplexityAnalyzer/ExecutionOptions.QueryComplexityAnalyzer. - Added per-field rate limiting via
field.AddRateLimit("policy-name").EntityGraphQL.AspNetships aPartitionedRateLimiter-backed default registered withservices.AddGraphQLFieldRateLimit(opts => { opts.AddFixedWindowPolicy(...); opts.AddConcurrencyPolicy(...); ... }). Rate limits count per-selection (aliases each burn a permit) and supportuserSpecific: truepartitioning by user key. - Added support for document descriptions as outlined in the latest 2025 spec. Basically string comments in the query document
- #474 - Add support for
TimeSpanas a scalar in the default schema - #500 - Expose parsed executable directive metadata via
BaseGraphQLField.Directivesby makingGraphQLDirective.NameandGraphQLDirective.Processorpublic for custom query processing scenarios - Replaced the previous 3rd party GraphQL document parser.
- Add
net10.0as a target - When using Offset Paging the total items expression is now only executed if the query requests
hasNextPageortotalItemsfields - When using Connection Paging the total count expression is now only executed if the query requests
totalCountorpageInfofields or the 'last' argument is used - Added
IField.AsService()to signal that a field should (or can) be treated as a service field. This means null-checks are differently and they are executed after EF related calls (ifExecutionOptions.ExecuteServiceFieldsSeparately = true). Useful for fields that operate with data fully in-memory and do not need a registered service to fetch data or work AddGraphQLSchemain ASP.NET now automatically detects and applies environment-based defaults:- Uses
PolicyOrRoleBasedAuthorizationby default (instead of requiring explicit configuration) - Automatically sets
IsDevelopment = falsein non-Development environments
- Uses
- Subscription fields now support
Task<IObservable<T>>andValueTask<IObservable<T>>as return types in addition toIObservable<T>. This allows subscription setup methods to be async, which is useful when subscribing to an external message broker (Redis, RabbitMQ, etc.) requires an async connection step.
Fixes
- Rewrote WebSocket subscription send path (
GraphQLWebSocketServer) to use aChannel-backed drain task. All outbound frames are now serialised through a single writer, eliminating the concurrentWebSocket.SendAsyncviolation that could corrupt the frame stream when multiple subscriptions fired simultaneously. TheIObserver<T>callbacks (OnNext/OnError/OnCompleted) now enqueue to the channel rather than blocking onGetAwaiter().GetResult(), freeing the observable/Redis thread immediately.subscriptionsdictionary replaced withConcurrentDictionaryfor thread-safety. - Fixed
SelectWithNullCheckerror when using.ResolveAsync<TService>()on a field that returns a list of complex objects with subfield selection (e.g.toolCatalog { name }), where the parent field returns a single object. In the two-pass execution path the element-type parameter was incorrectly derived fromTask<IEnumerable<T>>rather thanT, and the resolved collection was not preserved as a typedList<T>when rebuilding the async result graph. - #498 - Fixed introspection types and fields incorrectly using the configured
FieldNamer. Spec-defined introspection names now remain standard camelCase even when the application schema uses a custom naming convention. - #486 - Fixed directives on root-level fields failing to resolve query variable arguments (e.g.
@include(if: $var)).OpVariableParameteranddocVariableswere not being passed through to directive evaluation inGraphQLQueryStatement, causing any directive that references a variable to throw a type-mismatch error. - #481 - handle
ResolveAsyncon a top level field - #488 - Support async fields with
[GraphQLField] - #487 - Fix
ResolveAsyncwith arguments - #484 - Better support for nullable numeric types in filter expressions. Nullable int/short/long fields can now be compared to numeric literals without type mismatch errors. The fix also prioritizes converting literals over field expressions to avoid database column casts that could prevent index usage.
- #459 - Fixed error "variable 'service' ... is not defined" when using
Resolve<TService>()directly on a field that also usesUseConnectionPaging()orUseOffsetPaging(). When the paging field's own resolver depends on a service, the field now falls back to single-pass execution so the service parameter is always in scope. Fields with services on child types (not the paging field itself) continue to use the normal two-pass execution path where the DB query runs first and the service is resolved in-memory against the paged results. - As per spec -
_Type.fieldsshould benullforINPUT_OBJECT. Previously theinputFieldswere repeated.
5.7.2
Fixes
- #512 - Updated
HotChocolate.Languagedependency from 13.9.14 to 13.9.16 to resolve critical vulnerability (GHSA-qr3m-xw4c-jqw3: stack overflow via deeply nested GraphQL documents)
6.0.0-beta2
Changes
- Added
selectManymethod support to filter expressions, enabling flattening using nested collections within queries.
Fixes
- Fixed (maybe a regression introduced in 6.0.0-beta1)
UseFilter()incorrectly adding a default value to the filter argument when applied to fields that already have other arguments defined.
6.0.0-beta1
Breaking Changes
-
Support for partial results as per spec. This actually fixes EntityGraphQL to follow the GraphQL spec regarding partial results. However it does change behavior.
- EntityGraphQL basically executes each "top level" field in the operation separately, now if any fail, you'll get the partial results of those that succeeded and error information about the failed ones.
AddGraphQLValidatornow registersIGraphQLValidatorasTransient. This was the original intent as the docs have examples of bailing early by checking if the validator has any errors. The intent was errors for that field. This change helps enable partial results. If you want the old behavior, remove the use ofAddGraphQLValidatorand just addIGraphQLValidatoryourself asScoped- As per spec If an error was raised during the execution that prevented a valid response, the "data" entry in the response should be null. This was not always the case
-
Removed methods/properties marked as obsolete
IField.UseArgumentsFromFielduseGetExpressionAndArgumentsIField.UseArgumentsFromuseGetExpressionAndArgumentsIField.ResolveWithServiceuseResolveIFieldExtension.GetExpressionuse the newGetExpressionAndArguments
-
MapGraphQLfollowSpec = trueis now the default behavior, it follows https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md -
You can no longer add filter support by using
ArgumentHelper.EntityQueryorEntityQueryTypein the field args, e.g.schemaProvider.Query().ReplaceField("users", new { filter = ArgumentHelper.EntityQuery<User>() }, "Users optionally filtered"). Please use theUseFilterextension which supports filters referencing service fields. -
IFieldExtension.GetExpressionAndArgumentsnow takes the current GraphQL nodeBaseGraphQLField fieldNodeas an argument.parentNodehas been removed. Access it viafieldNode.ParentNode. -
EntityGraphQL.AspNetpackage dropsnet6.0andnet7.0as targets.EntityGraphQLpackage dropsnet6.0as a target however as it still targetsnetstandard2.1you can still use it with those previous dotnet versions.
Changes
- Partial results support
- #467 - New implementation for handling
asyncfields. See updated docs and use the.ResolveAsync<>()methods when adding fields. - New support for
CancellationToken. ACancellationTokencan be passed into theExecuteRequestAsyncmethod. The token will be checked throughout execution and passed to other async operations. You can use it in.ResolveAsync<MyService, CancellationToken>((context, service, ct) => service.DoSomethingAsync(context.Field, ct))to pass it to yourasyncfields. If you useMapGraphQL()for ASP.NET it will use thecontext.RequestAbortedas the cancellation token. - #469 - Make filter grammar immutable as it should be for performance
- #303 - You can now reference service fields in the
UseFilter/[UseFilter]expression. Like normal the filter will first be applied with non service fields, then applied again with service fields isExecutionOptions.ExecuteServiceFieldsSeparately == true(default). - #396 - Filter expressions now support GraphQL variables using
$variableNamesyntax. This allows parameterized and dynamic filters (e.g.,filter: "name == $searchTerm && age > $minAge"). - Related to #331 and the
followSpec = trueabove, errors and exceptions were refactored internally. Following the GraphQL spec if the core library gets an error it will still return aGraphQLResultwith the errors (and potentially partial results).
Fixes
- #429 Validation attributes now work with
[GraphQLInputType]
Full Changelog: 5.7.1...6.0.0-beta1
5.7.1
Fixes
- #466 Include enum-typed input fields in introspection per GraphQL spec
Full Changelog: 5.7.0...5.7.1
5.7.0
Changes
- QueryInfo Support: Added optional query execution information that can be included in the result extensions. Enable with
ExecutionOptions.IncludeQueryInfo = trueto get metadata about:- Operation type (Query, Mutation, Subscription)
- Operation name
- Types queried and their selected fields
- Total number of types and fields queried
- This is useful for query analysis, debugging, and monitoring GraphQL usage patterns
- Fix #441 (PR #455) - Have your argument class (including an
InputType) class inheritArgumentsTrackeror implementIArgumentsTrackerto be able to tell if a variable is just the dotnet default value or is set from the query (variable or inline) withargs.IsSet. You can also includeIArgumentsTrackeras an argument in your mutations etc. This is useful if you method usings simple arguments e.g.MyMutation(Guid id, string name)vs. a[GraphQLArguments]object. - #461 -
EntityGraphQLEndpointRouteExtensions.MapGraphQLnow supports chunked requests RequiredAuthorizationis not settable allowing you to change or overwrite it after creation. Also now hasClear()methods to remove authentication
Fixes
- Throw error on a query that has fragments with a cycle as per the GraphQL spec and to prevent infinite loops.
- #442 - Fix issue when a service field with a bulk resolver is on a parent field named differently to the dotnet underlying object property
5.6.1
Fixes
- #443 - Allow
*/*&application/*Acceptheaders infollowSpecoption forMapGraphQL - #443 - Allow expected headers to not be listed first when using
followSpecoption forMapGraphQL - Better support for multiple items in a single
Acceptheader when usingfollowSpecoption forMapGraphQL - #449 - Fix issues with self referencing query and connection paging