Skip to content

Releases: EntityGraphQL/EntityGraphQL

6.0.0-beta6

6.0.0-beta6 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 12 Jun 12:57

Breaking Changes

  • #515 - DefaultGraphQLResponseSerializer and DefaultGraphQLRequestDeserializer default JsonSerializerOptions now use JsonSerializerDefaults.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.MaxQueryNodes renamed to MaxFieldSelections — it counts field selections (the GraphQL spec term) after fragment expansion, not AST or result nodes.
  • ExecutionOptions.UserKeySelector renamed to RateLimitUserKeySelector to reflect that it only affects per-field rate limiters tagged userSpecific: true.

6.0.0-beta5

6.0.0-beta5 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 12 Jun 11:13

Breaking Changes

  • AddGraphQLOptions<TContext> now exposes overloaded ConfigureSchema(...) methods instead of settable schema-configuration delegate properties. Use options.ConfigureSchema(schema => { ... }) for the common case, or options.ConfigureSchema((schema, services) => { ... }) when schema setup needs the active IServiceProvider.
  • AddGraphQLSchema() in EntityGraphQL.AspNet now returns a dedicated GraphQLSchemaBuilder<TContext> instead of IServiceCollection. Schema-shape customization should now be chained with ConfigureGraphQLSchema(...), for example:
    • services.AddGraphQLSchema<MyContext>(options => { ... }).ConfigureGraphQLSchema<MyContext>(schema => { ... });

Changes

  • #508 - Added a src/examples/tooling example showing GraphiQL and Hot Chocolate Nitro hosted against an EntityGraphQL.AspNet /api/graphql endpoint.
  • Query/document errors now preserve structured source locations in addition to the existing message text, and GraphQLError responses now emit locations metadata when available. Also normalized invalid field-directive registration to throw EntityGraphQLSchemaException instead of InvalidOperationException on the public schema API surface.
  • #515 - The MapGraphQL endpoint no longer silently swallows exceptions. Response execution/serialization failures (HTTP 500) are now logged at Error and request rejections (406/415/400, including request-body deserialization failures) are logged at Debug via the standard ILogger infrastructure, so serialization issues like graph-cycle exceptions from RuntimeTypeJsonConverter are diagnosable. The SchemaProvider<TContext> logger is now wired up from DI in EntityGraphQL.AspNet, so query execution errors are logged as well.
  • #515 - DefaultGraphQLResponseSerializer now exposes its default JsonSerializerOptions via the static DefaultGraphQLResponseSerializer.CreateDefaultOptions(), so the defaults can be tweaked (e.g. removing RuntimeTypeJsonConverter) without reproducing every setting by hand. The default options now also use JsonSerializerDefaults.Web.

Full Changelog: 6.0.0-beta4...6.0.0-beta5

6.0.0-beta4

6.0.0-beta4 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 23 Apr 00:01

Breaking Changes

  • Simplified IFieldExtension compilation hooks by replacing long positional parameter lists with context objects:
    • GetExpressionAndArguments() now takes FieldExtensionExpressionContext
    • ProcessExpressionPreSelection() now takes FieldExtensionPreSelectionContext
    • ProcessExpressionSelection() now takes FieldExtensionSelectionContext

Changes

  • #513 - AddGraphQLSchema() now supports configuring the registered SchemaProvider<TContext> lifetime via AddGraphQLOptions.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

6.0.0-beta3 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 20 Apr 07:23

Breaking Changes

  • Fields in ExecutableDirectiveLocation enum have been renamed in C# style
  • #476 - Introduce generic custom type converters (from-to, to-only, from-only) for flexible runtime value conversion.
    • Expand isAny to support additional types through the method provider
    • Removes ICustomTypeConverter. See updated docs and the more flexible converting methods available
  • Renamed SchemaBuilderSchemaOptions to SchemaProviderOptions for better clarity between schema builder reflection options and schema provider configuration options
  • AddGraphQLOptions<TSchemaContext> refactored from inheritance to composition:
    • Now exposes Builder property for SchemaBuilderOptions (controls building/reflection behavior)
    • Now exposes Schema property for SchemaProviderOptions (controls schema provider configuration like authorization, introspection, error handling, field naming)
    • Removed FieldNamer property - now accessed via options.Schema.FieldNamer
    • PreBuildSchemaFromContext moved from SchemaProviderOptions to SchemaBuilderOptions - now accessed via options.Builder.PreBuildSchemaFromContext (it's called during the schema building phase, not runtime)
  • Removed introspectionEnabled parameter from AddGraphQLSchema extension method - configure via options.Schema.IntrospectionEnabled instead
  • Authorization refactoring: RequiredAuthorization now uses a keyed data structure for extensibility
    • RequiredAuthorization no longer has separate Roles backing field - roles are stored via "egql:core:roles" key in KeyedData dictionary
    • The Roles property is now nullable and computed from keyed data
    • Policy support moved entirely to EntityGraphQL.AspNet package using "egql:aspnet:policies" key
    • RequiredAuthorization constructor that took roles parameter has been removed - use RequiresAnyRole() or RequiresAllRoles() methods instead
    • Custom authorization implementations should use namespaced keys (e.g., "myapp:custom-auth") to avoid conflicts
  • Added withoutServiceFields parameter to IFieldExtension.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) to ExecutionOptions. All default to unlimited (opt-in). A limit violation returns a GraphQL DocumentError and prevents any resolver from running. Configure in ExecutionOptions in your call to schema.ExecuteRequest(...).
  • Added complexity scoring via field.SetComplexity(int) (fixed cost) or field.SetComplexity(ctx => ctx.Args.take * (1 + ctx.ChildComplexity)) (args-aware). Pluggable via IQueryComplexityAnalyzer / ExecutionOptions.QueryComplexityAnalyzer.
  • Added per-field rate limiting via field.AddRateLimit("policy-name"). EntityGraphQL.AspNet ships a PartitionedRateLimiter-backed default registered with services.AddGraphQLFieldRateLimit(opts => { opts.AddFixedWindowPolicy(...); opts.AddConcurrencyPolicy(...); ... }). Rate limits count per-selection (aliases each burn a permit) and support userSpecific: true partitioning 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 TimeSpan as a scalar in the default schema
  • #500 - Expose parsed executable directive metadata via BaseGraphQLField.Directives by making GraphQLDirective.Name and GraphQLDirective.Processor public for custom query processing scenarios
  • Replaced the previous 3rd party GraphQL document parser.
  • Add net10.0 as a target
  • When using Offset Paging the total items expression is now only executed if the query requests hasNextPage or totalItems fields
  • When using Connection Paging the total count expression is now only executed if the query requests totalCount or pageInfo fields 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 (if ExecutionOptions.ExecuteServiceFieldsSeparately = true). Useful for fields that operate with data fully in-memory and do not need a registered service to fetch data or work
  • AddGraphQLSchema in ASP.NET now automatically detects and applies environment-based defaults:
    • Uses PolicyOrRoleBasedAuthorization by default (instead of requiring explicit configuration)
    • Automatically sets IsDevelopment = false in non-Development environments
  • Subscription fields now support Task<IObservable<T>> and ValueTask<IObservable<T>> as return types in addition to IObservable<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 a Channel-backed drain task. All outbound frames are now serialised through a single writer, eliminating the concurrent WebSocket.SendAsync violation that could corrupt the frame stream when multiple subscriptions fired simultaneously. The IObserver<T> callbacks (OnNext/OnError/OnCompleted) now enqueue to the channel rather than blocking on GetAwaiter().GetResult(), freeing the observable/Redis thread immediately. subscriptions dictionary replaced with ConcurrentDictionary for thread-safety.
  • Fixed SelectWithNullCheck error 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 from Task<IEnumerable<T>> rather than T, and the resolved collection was not preserved as a typed List<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)). OpVariableParameter and docVariables were not being passed through to directive evaluation in GraphQLQueryStatement, causing any directive that references a variable to throw a type-mismatch error.
  • #481 - handle ResolveAsync on a top level field
  • #488 - Support async fields with [GraphQLField]
  • #487 - Fix ResolveAsync with 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 uses UseConnectionPaging() or UseOffsetPaging(). 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.fields should be null for INPUT_OBJECT. Previously the inputFields were repeated.

5.7.2

Choose a tag to compare

@lukemurray lukemurray released this 20 Apr 06:01

Fixes

  • #512 - Updated HotChocolate.Language dependency 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

6.0.0-beta2 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 01 Dec 22:09

Changes

  • Added selectMany method 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

6.0.0-beta1 Pre-release
Pre-release

Choose a tag to compare

@lukemurray lukemurray released this 16 Sep 00:35

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.
    • AddGraphQLValidator now registers IGraphQLValidator as Transient. 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 of AddGraphQLValidator and just add IGraphQLValidator yourself as Scoped
    • 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.UseArgumentsFromField use GetExpressionAndArguments
    • IField.UseArgumentsFrom use GetExpressionAndArguments
    • IField.ResolveWithService use Resolve
    • IFieldExtension.GetExpression use the new GetExpressionAndArguments
  • MapGraphQL followSpec = true is 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.EntityQuery or EntityQueryType in the field args, e.g. schemaProvider.Query().ReplaceField("users", new { filter = ArgumentHelper.EntityQuery<User>() }, "Users optionally filtered"). Please use the UseFilter extension which supports filters referencing service fields.

  • IFieldExtension.GetExpressionAndArguments now takes the current GraphQL node BaseGraphQLField fieldNode as an argument. parentNode has been removed. Access it via fieldNode.ParentNode.

  • EntityGraphQL.AspNet package drops net6.0 and net7.0 as targets. EntityGraphQL package drops net6.0 as a target however as it still targets netstandard2.1 you can still use it with those previous dotnet versions.

Changes

  • Partial results support
  • #467 - New implementation for handling async fields. See updated docs and use the .ResolveAsync<>() methods when adding fields.
  • New support for CancellationToken. A CancellationToken can be passed into the ExecuteRequestAsync method. 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 your async fields. If you use MapGraphQL() for ASP.NET it will use the context.RequestAborted as 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 is ExecutionOptions.ExecuteServiceFieldsSeparately == true (default).
  • #396 - Filter expressions now support GraphQL variables using $variableName syntax. This allows parameterized and dynamic filters (e.g., filter: "name == $searchTerm && age > $minAge").
  • Related to #331 and the followSpec = true above, errors and exceptions were refactored internally. Following the GraphQL spec if the core library gets an error it will still return a GraphQLResult with 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

Choose a tag to compare

@lukemurray lukemurray released this 12 Aug 06:40

Fixes

  • #466 Include enum-typed input fields in introspection per GraphQL spec

Full Changelog: 5.7.0...5.7.1

5.7.0

Choose a tag to compare

@lukemurray lukemurray released this 06 Aug 11:56

Changes

  • QueryInfo Support: Added optional query execution information that can be included in the result extensions. Enable with ExecutionOptions.IncludeQueryInfo = true to 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 inherit ArgumentsTracker or implement IArgumentsTracker to be able to tell if a variable is just the dotnet default value or is set from the query (variable or inline) with args.IsSet. You can also include IArgumentsTracker as 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.MapGraphQL now supports chunked requests
  • RequiredAuthorization is not settable allowing you to change or overwrite it after creation. Also now has Clear() 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

Choose a tag to compare

@lukemurray lukemurray released this 28 Apr 01:20

Fixes

  • #443 - Allow */* & application/* Accept headers in followSpec option for MapGraphQL
  • #443 - Allow expected headers to not be listed first when using followSpec option for MapGraphQL
  • Better support for multiple items in a single Accept header when using followSpec option for MapGraphQL
  • #449 - Fix issues with self referencing query and connection paging