- #443 - Allow
*/*
Accept
header infollowSpec
option forMapGraphQL
- Added additional framework target
net9.0
ResolveWithService
andResolveWithServices
methods are now marked obsolete. Please useResolve
in the same way- #430 -
MapGraphQL
has new parameterfollowSpec
which changes the behavior to follow https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md and isfalse
by default in v5.x. If set totrue
it will follow the spec, the major change being that if the HTTP request was valid you'll get a200
status code even if there may be GraphQL errors in the response. Note this will be the default behavior in version v6. - Add
IsNullable
to theIField
interface to control setting the nullability of the field return type in the schema
- #435 - fix
isAny()
infilter
- Fix issue selecting fields from an object a service field returns where the GraphQL field name differs from the dotnet property name.
Example a field that returns a User
type using a service and you are changing the field names in the schema like below
schema.Type<User>().AddField("username", u => u.Name, "Username")
- #439 - Fix using fields / properties with key words (
null
,true
,false
) at the start of the name in the filter expressions - Related to #430 - Make sure if the schema says a field is not nullable, that it is not returned as
null
when usingnull
to exit a mutation or field on error. - Fix issue where an expression extracted from a service field may clash with a existing field name
- #432 - filter expression was incorrectly using bit-wise
Or
instead ofOrElse
- #418 - Fix issue where field expressions using
ctx.Entities.FirstOrDefault(<filter>)
(First*
,Last*
,Single*
methods with a filter) would duplicate the filter expression on each execution (e.g. makingctx.Entities.Where(<filter>).Where(<filter>).FirstOrDefault()
). This also caused EntityFramework not to use it's cache for the expression - Fix issue with
RequiresAnyRole()
being called on a field with multiple roles added them as requiring all those roles vs. any role. This did not effect the[GraphQLAuthorize]
attribute
- #425 - As per GraphQL Spec, Interfaces are not supported for Input Types
- #426 - Fix custom directives with no arguments.
- #427/#428 - Fix issue with connection style paging field extension when using last and before arguments
- Add
IgnoreAttributes
toSchemaBuilderOptions
- A list of Attribute types which will cause the builder to ignore the field/property when building the schema. These are additional to GraphQLIgnoreAttribute .Resolve<>()
method on field changes return type toobject?
to avoid warnings when returning a valid nullable service call etc.- Add support for using a
struct
type as an object type in the schema, allowing you to query the fields on it. Previously it only worked if you added thestruct
as a Scalar Type - #419 - Add support for using
isAny([])
on nullable types
- Make sure top level types have access checked (Query, Mutation and Subscription)
- Fix #392 - Better handle
null
checks when executing against in-memory data - #363 - Only use
ToListWithNullCheck
when we know we are executing with services, or have been told not to separate the execution.
- Fix issue with inline arguments for mutation methods not being validated or trying to look for a service. e.g.
[GraphQLMutation]
public static Expression<Func<MyContext, Movie>> AddMovie(
[Required(ErrorMessage = "Title is required")] string title,
[Range(1, 100, ErrorMessage = "Price must be between $1 and $100")] decimal price,
[StringLength(5, ErrorMessage = "Rating must be less than 5 characters")] string rating
)
- Fix auth not correctly being checked for mutations or subscriptions. Issue was introduced in 5.4.2
- Argument validator was incorrectly traversing types and properties it shouldn't which could cause stack overflows for some types
- Fix validating inline arguments for mutation methods
- #399 - Serialize
null
values if the field is requested as per the GraphQL spec - Make sure the naming policy set in
DefaultGraphQLResponseSerializer
is used for all fields
- #393 - Handle
DateTimeOffset
in filter expressions - #398 - Make sure user credentials are not cached if using the compiled query cache
- #370 - Sort field extension (
[UseSort]
or.UseSort()
), if building the sort argument input type from the dotnet fields/properties will now respect the[GraphQLIgnore]
attribute on any fields. - #386 / #387 - Fix regressions in filter expressions
- #367 - Remove Antlr dependency for generating the filter expression parser. Replaced with Parlot, a dotnet only solution to remove a barrier for contributors. This also results in the filter (FilterExpression field extension) expressions being compiled up to twice as fast.
- #334 - add
isAny([])
method to the filter expression language Broadcaster
exposes its properties and methods are virtual allowing you to extend its functionality instead of writing your own fully- #374 - Sort field extension now has an
useSchemaFields
option. This will use the fields on the type you are sorting from the schema to build the input argument. Instead of the fields on the dotnet type. Because the input type is build once at the beginning it will only include schema fields currently known at the time you call.UseSort()
. - #375 - Allow specifying
introspectionEnabled
when calling theAddGraphQLSchema
extension methods - #222 - EntityGraphQL can now build a argument objects via their constructor. The parameter names need to match the field names. E.g.
// empty constructor - the properties set are called
public class PersonArg
{
public string name { get; set; }
}
// with a constructor
public class PersonArgConstructor
{
public PersonArgConstructor(string name)
{
Name = name;
}
public string Name { get; }
}
- Fix issue where a subscription execution had access to a disposed
IServiceProvider
Broadcaster
is thread safe when removing observers- Fixes in the implementation of the GraphQL over Websockets
- ID is now a
string
as it does not specify that it must be aGuid
- Better errors on invalid messages
- ID is now a
ISchemaProvider.Validate()
added to allow you to validate the schema is complete to avoid potential errors at runtime/query time. As fields and types can be added to the schema out of dependency order, this checks that all required types are in the schema.- #362 - The Sort field extension now supports defining more complex sort expressions that will be used. E.g.
schema.Type<TestDataContext>().GetField("people", null)
.UseSort((Person person) => new
{
// [{managerName: ASC}] in GQL can be used and the full expression person.Manager.Name will be used in the OrderBy()
managerName = person.Manager.Name,
});
-
#169 -
ExecutionOptions
now has aBeforeRootFieldExpressionBuild
callback you can use to make modifications to a fields expression before it is then used to build the whole query. This is only called for root fields in your GraphQL operation. A common use case for this might be to call the EFTagWith
extension method passing it the operation name to help with debugging queries. -
#308 - Support a dotnet
Type
being used for an input type and a query type. This may change in future versions but some simple cases are now supported -
IField.UseArgumentsFrom
&IField.UseArgumentsFromField
is now Obsolete. Using it (typically in a field extension) creates issues. See #358 fix below -
IFieldExtension.GetExpressionAndArguments
has been added to allow field extensions to handle arguments and add them to the compile context. This interface will merge with the existing (now obsolete)IFieldExtension.GetExpression
in version 6.0. This was introduced to fix #358 and avoid breaking changes -
GetSchemaType(string typeName, QueryRequestContext? requestContext)
is now Obsolete, useGetSchemaType(string typeName, bool inputTypeScope, QueryRequestContext? requestContext)
and provideinputTypeScope = true
if the type is an Input type. -
#359 - For targets .net6 and above
DateOnly
&TimeOnly
are added as scalar types by default.
- #356 - Look up the correct field return type for
InputType
s - #358 -
OffsetPaging
andConnectionPaging
field extensions can now be used on multiple fields that return the same type. e.g. - #148 - Return a more descriptive error message for a missing type when we know the field we are trying to find the type of
- #361 - Handle union/interface types when accessed from a object projection
// both fields return a list of people but have different expressions
schema.Query().AddField("peopleOver", new
{
over = ArgumentHelper.Required<int>()
},
(ctx, args) => ctx.People.Where(p => p.Height > args.over).OrderBy(p => p.Id), "Return list of people with paging metadata")
.UseOffsetPaging();
schema.Query().AddField("peopleUnder", new
{
under = ArgumentHelper.Required<int>()
},
(ctx, args) => ctx.People.Where(p => p.Height < args.under).OrderBy(p => p.Id), "Return list of people with paging metadata")
.UseOffsetPaging();
- #355 - make error variable values more distinctive
- EntityGraphQL is now more specific in which methods it tries to optimize the pattern of a list to single. E.g. If a field has an expression like
ctx => ctx.People.FirstOrDefault(filter)
EntityGraphQL treats that as a ListToSingle field and will build a full expression similar toctx => ctx.People.Where(filter).Select(x => new {...}).FirstOrDefault()
to avoid over fetching when using EntityFramework. Previously EntityGraphQL would try to break up and rebuild expressions.methods it didn't know how to. It now correctly only tries this optimization onFirst
,FirstOrDefault
,Single
,SingleOrDefault
,Last
&LastOrDefault
fromQueryable
&Enumerable
Check release notes for the 5.2.0-beta1 and beta2 below.
- #347 - The handler for the subscriptions end point added by
UseGraphQLWebSockets
no longer returns400
if the request is not a web socket request. Allowing the request to get passed to the next handlers. This allows you to have the same endpoint for queries/mutations and subscriptions.
- #350 - Index accessors properties (which are methods to dotnet) on types are ignored when using
SchemaBuilder
. Previously they would fail. - #333 - Fixes to method and service calls on interfaces/unions
- #344 - Support paging field extensions with
field.ResolveBulk<TService, TKey, TResult>()
- Fix bulk resolve services within a List to Single node
Check release notes for the 5.2.0-beta1 below.
- Fix error when using a service at a query root field that uses
First()
as friends (List to single pattern). E.g.(ctx, service) => ctx.SomeList.First(i => i.Thing == service.Other)
- #318 - Fix issue comparing
int
style fields againstfloat
style fields in the filter expression - Better error message when comparing different enum types in the filter language
- Include descriptions for scalars and directives in introspection and schema output
- Fix issue using the default
SchemaBuilderOptions
with a mutation method that has a list argument. The argument input type was not being correctly added to the schema. Not an issue if you were already adding the type manually - #336 - Fix conversion of non-nullable/nullable types
- #342 - Fix argument incorrectly being renamed when using
[GraphQLField]
- #318 - Support Unicode characters in the string of the filter language
- Support more cases with
field.ResolveBulk<TService, TKey, TResult>()
- Add a net8.0 target output for the base EntityGraphQL library.
- Make more properties public in nodes like
GraphQLCollectionToSingleField
to better support customisation in custom directives - Added
field.Resolve<TService, ...>()
to replaceResolveWithService<>()
. Recommended to useResolve()
. Release 5.3 will markResolveWithService
as deprecated and release 6.0 will remove them. - Add
field.ResolveBulk<TService, TKey, TResult>()
to allow you to use services to bulk load data to avoid multiple calls to a service resolve expression that may call an external service in a list result. Example - Add
schema.AddEnum<TEnum>(typeName, description)
to the schema building API - Add
net8.0
as a target for EntityGraphQL.AspNet project
var schema = SchemaBuilder.FromObject<MyContext>();
schema.UpdateType<Project>(type =>
{
type.ReplaceField("createdBy", "Get user that created it")
// normal service to fetch the User object for creator of the Project type
.ResolveWithService<UserService>((proj, users) => users.GetUserById(proj.CreatedById))
// Bulk service used to fetch many User objects
.ResolveBulk<UserService, int, User>(proj => proj.CreatedById, (ids, srv) => srv.GetAllUsers(ids));
});
If you have a query like
{
# ResolveBulk
projects {
# project fields
name
id
# service field - resolved with ResolveBulk expression for all Projects loaded
createdBy {
name
}
}
# ResolveWithService
project(id: 78) {
# project fields
name
id
# service field - resolved with ResolveWithService expression for the single project loaded
createdBy {
name
}
}
}
Instead of calling users.GetUserById()
for each project to resolve createdBy { name }
, EntityGraphQL will build a list of keys using the proj => proj.CreatedById
expression from the list of projects and then call the (ids, srv) => srv.GetAllUsers(ids)
expression once for the whole list of projects in the results. See updated documentation for further details.
- Fix #337 - Description attribute accidentally updating name instead of description
- Upgrade to the latest standard Antlr4 - the parser/tool used for the filter expression strings. Fixing precedence of operators
- #319 - Only convert strings to
Guid
orDateTime
when required - If you add a field connecting back to the Query Context that ends in a method to go from a list to a single result the graph object projection will now correctly be inserted before the last call. Example
var schema = SchemaBuilder.FromObject<MyContext>();
schema.AddType<ExternalData>("ExternalData").AddAllFields();
schema.UpdateType<ExternalData>(ed =>
{
// connect back to the MyContext types
ed.AddField("movie", "Get movie")
// here FirstOrDefault() goes from list -> single
.ResolveWithService<MyContext>((ed, db) => db.Movies.Where(m => m.Id == ed.Id).FirstOrDefault());
});
schema.Query().AddField("externalData", "Get Data")
.ResolveWithService<ExternalDataService>((p, srv) => srv.GetData());
In the above case if you select
{
externalData {
movie {
director {
name
}
}
}
}
The movie field will have the selection inserted allowing EF to resolve fields without lazy loading turned on. Without this the m.Director.Name
would also be null
as no relation was included. e.g.
db.Movies.Where(m => m.Id == ed.Id)
.Select(m => new [
director = new {
name = m.Director.Name
}
])
.FirstOrDefault();
- Fix #314 - Some clean up of the Antlr4 grammar for the filter expressions
Make sure to check out the changes 5.0.0-beta1
- Generated schema type name for field sort inputs now include the name of the schema type the field is on to avoid conflicts
IField.AddExtension
now returns theIField
UseSort()
field extension now can take a list of default sort fields e.g.Broadcaster
(inbuiltIObservable<TType>
you can use for subscriptions) now has aOnUnsubscribe
callback
schema.ReplaceField("people",
ctx => ctx.People,
"Return a list of people. Optional sorted")
.UseSort(
new Sort<Person>((person) => person.Height, SortDirection.ASC),
new Sort<Person>((person) => person.LastName, SortDirection.ASC)
);
SchemaBuilderOptions
now has aOnFieldCreated
callback to make changes to fields asSchemaBuilder
is building the schema..contains(string)
,.startsWith(string)
,.endsWith(string)
&.toLower()
/.toUpper()
string methods now available in the filter argument expression.
- Fix naming of fields extracted from service calls when those field use convert
EntityGraphQL.AspNet
now targetsnet6.0
andnet7.0
, dropping targetsnetcoreapp3.1
andnet5.0
. You can still use the baseEntityGraphQL
library with older targets.- Interface
IExposableException
has been removed. UseSchemaBuilderSchemaOptions.AllowedExceptions
or the newAllowedExceptionAttribute
to define which exceptions are rendered into the results - #254 - Previously passing
null
for theClaimsPrincipal
inExecuteRequest()
would skip any authorization checks. All authorization checks are now done regardless of theClaimsPrincipal
value. Meaningnull
will fail if there is fields requiring authorization. IDirectiveProcessor
interface has changed. See upgrade docs for changesSchemaBuilderMethodOptions
removed, see updated properties onSchemaBuilderOptions
and upgrade docs. This was because you can also now add methods as query fields withGraphQLFieldAttribute
SchemaBuilderOptions.AutoCreateInputTypes
now defaults totrue
. Meaning inSchemaBuilder
when adding mutations etc any complex types will be added to the schema if they are not there already.- The rules for reflection on method parameters have been changed to make them clearer. See the upgrade to 5.0 docs and the mutation docs that cover examples.
GraphQLValidator
is no longer magically added to your method fields (mutations/subscriptions). If you wish to use it please register it in your services. There is a new helper method in EntityGraphQL.AspNetAddGraphQLValidator()
. This means you can implement and register your own implementation.SchemaProvider.ExecuteRequest
&SchemaProvider.ExecuteRequestAsync
have been renamed toExecuteRequestWithContext
&ExecuteRequestWithContextAsync
. The schema context instance provided will be used for all context references within that query.- #309 - Introduced new
SchemaProvider.ExecuteRequest
&SchemaProvider.ExecuteRequestAsync
which take no schema context instance as an argument. The context will be fetched from the providedServiceProvider
meaning the lifetime rules are adhered to - e.g.ServiceLifetime.Transient
is now correctly used. This is the preferred way to execute a query
EntityGraphQL
(the core library) targets bothnetstandard2.1
&net6
.netstandard2.1
will be dropped around the time ofnet8.0
being released.- Introduced
GraphQLFieldAttribute
to allow you to rename fields in the schema as well as mark methods as fields in the schema. Method parameters will become field arguments in the same way as mutation methods. See updated docs for more information. - Argument types used for directives now read
DescriptionAttribute
andGraphQLFieldAttribute
to use different field name in the schema and set a description - Added
GraphQLInputTypeAttribute
. WhereasGraphQLArgumentsAttribute
flattens the types properties into the schema,GraphQLInputTypeAttribute
assumes the type is an input type and uses that as the schema argument - You may implement you own
GraphQLValidator
by implementing (and registering)IGraphQLValidator
- Added a
options.BeforeExecuting
callback to allow modification of the expression before execution
- #266 - Fix error calling
AddPossibleType()
when some of the types have already been added to the schema ExecutionOptions
passed intoIApplicationBuilder.UseGraphQLWebSockets()
are now used when executing the queries for the subscription- #284 - Support generic class types as mutation arguments.
MyClass<OtherClass>
will becomeinput MyClassOtherClass {}
- #302 - Fix issue where using service fields with
IQueryable
/DbContext
fields
- Fix issue using the
OneOf
directive withArgumentHelper.Required<T>()
in a query field argument.
- #285 - Add support for implicit operators when converting types
- Fix how EntityGraphQL evaluates the root level fields that return lists. If the return type of the field is nullable a
null
will be returned if the result isnull
. If the return type is non-nullable an emptyList<T>
will be returned.
public class UserDbContextNonNullable
{
// empty list will be returned if UserIds resolves to null. If you use nullable types you can control with the ? operator (to return null)
[GraphQLNotNull]
public List<string> UserIds { get; set; }
}
- #288 - fix stack overflow in
RuntimeTypeJsonConverter
- #291 - Fix
ResolveWithService
being called twice due toExpression.Condition
if the field is a list and at the root level of the Query type
- Fix issue selecting repeated fields from an interface and a fragment selection
- Fix issue selecting interface fields from the concrete type in a fragment
- #281 - Implement allowed exceptions to allow exceptions to come into the error result when running with
IsDevelopment == false
as users not be able to modify the exceptions being thrown in order to have them implementIExposableException
. Exceptions may be allowed with an exact type match, or allowed including all types that inherit it
- Prevent double SQL (when using against EF) query on base type (4.1 regression)
- #279 - Remove duplicate fields when creating expressions
- #280 - Fix for mutations that return interfaces/unions
- Fix issue when using paging extension and aliases in the query e.g.
{ myList { myEdges: edges { .. } } }
previously would fail
- #221 - Apply null check on the
ToList
expression built to resolve list expressions - Better support for service fields at the root query level
- Fix support for service fields that take a complex type (object or enumerable) as arguments
- Fix
UseFilter()
filter
andUseSort()
sort
field arguments were incorrectly being marked as required in schema introspection - Fix issues with default sort values for
UseSort()
not appearing in the schema as default values - Fix output of default values in schema for lists and objects
- #262/#205 - Option to prevent leaking internal exceptions into the 'errors' field on a result.
When running in development (read via IWebHostEnvironment.IsEnvironment("Development")
or when manually creating SchemaProvider
), messages of exceptions will not be dumped out into the 'errors' field of a query result, unless they implement the newly created (and empty) interface IExposableException
.
- #260 - Support default values in C# methods for mutations
- #264 - Versions prior to .NET 7,
System.Text.Json
doesn't support the serialization of polymorphic type hierarchies. EntityGraphQL now registers aRuntimeTypeJsonConverter
class as part of theDefaultGraphQLResponseSerializer
- #264 - Interface/union queries used to require you to query for at least 2 of the subtypes at once.
- Fix issue with service fields that take nullable type fields as arguments
- #248 - Make sure directives run on fields that map a list of items to a single item (e.g.
myItem(id: Int!) @include(...) { ... }
) - #213 - Multiple levels of
TargetInvocationException
will now be unwrapped - #82 - SchemaBuilder can now handle fields that return
Task<>
. Note that the way that queries expressions are built you may still encounter issues withasync
fields not at the root query level. Please open an issue if you do - #259 - Fix introspection of nullable/non-nullable lists with nullable/non-nullable items
- #239 - Fix issues rejoining main context from a service field
- #243 - support
application/json; charset=utf-8
content type
- Fix issue related to #235 where the multiple fields are the same field with different alias and arguments
IFieldExtension.ProcessExpressionSelection
now takes aParameterExpression? argumentParam
argument which is the argument parameter used at execution time (if there is one). Relating to #235
DateTimeOffset
is now added as a default scalar type in schema creation. It is a very common used type in EF contexts and trips up new users. If you previously were adding it as a scalar type you no longer need to. Or if you'd like to add it differently (like map it to Date) you can
services.AddGraphQLSchema<DemoContext>(options =>
{
options.PreBuildSchemaFromContext = (schema) =>
{
schema.RemoveType<DateTimeOffset>();
// add it how you want
};
});
AddMutationsFrom
and friends now take an optionalSchemaBuilderMethodOptions
options object to configure how mutations are built, following theSchemaBuilderOptions
used elsewhere. See updated docs. Important defaults:
bool AutoCreateInputTypes = true; // Any input types seen will be added to the schema
bool AddNonAttributedMethods = false; // GraphQLMutationAttributes are still required by default
bool AutoCreateNewComplexTypes = true; // Return types of mutations will be added to the schema
SchemaBuilderOptions.IgnoreTypes
Now usesType
instead ofstring
. It is aHashSet<Type>
now to avoid confusion of which name to use (full name space or not)ProcessExpressionSelection
used in Field Extensions now takesDictionary<IFieldKey, CompiledField>
for theselectionExpressions
parameter.IFieldKey
is the field name and the schema type the field belongs too. Helps when dealing with inline fragments/union types where we may have multiple fields with the same name from different types.MutationArgumentsAttribute
renamed toGraphQLArgumentsAttribute
and is used with subscriptions or mutation method arguments
- Add support for GraphQL subscriptions - see updated documentation
- Added support for defining Union types in the schema (#107)
- Core library
EntityGraphQL
only targetsnetstandard2.1
as we do not need to multi-target and this still supports a large dotnet base (3.1+)
- Fix #206 - If a service field included a binary expression EntityGraphQL would sometimes build an incorrect selection expression
- Fix #214 - The implicit conversion return type of a
ArgumentHelper.Required<>()
field argument is non-null - Fix #212 - Regression using a static or instance method in a service field
- Fix #223 - Mutations with inline args don't support variables with different name to argument name
- Fix #225 - Mutations with separate (not using
MutationArgumentsAttribute
) parameters fail if called without variables - Fix #229 - Using
Field.Resolve()
would incorrectly assume the field had a service - #219 - Handle conversion of variables as lists to a
RequiredField<>
arg of the list type - #215 - Fix issue using GraphQLValidator if using inline mutation arguments
- #235 - Fix issue where arguments with the same name at the same level in a query would receive the same value
- Fix #197 - If a mutation returns
Task<T>
useT
as the return type - Fix #204 - Nullable reference types correctly produce a nullable argument in the schema
- If not using
MutationArgumentsAttribute
in mutation methodsautoAddInputTypes
was being ignored
- Fix #194 -
HasType()
was not checking type mappings
- Prevent creation of invalid GraphQL schemas
- Exception is thrown if you try to add a field with arguments to types that do not support arguments -
Enum
&Input
types - Exception is thrown if you try to add fields to a
Scalar
type - Exception is thrown on invalid type name
- Exception is thrown if you try to add a field with arguments to types that do not support arguments -
- Schema builder now creates a valid GraphQL type name for generic types
- Enum types are now added to the schema as a typed
SchemaType<T>
instance. Meaning you can fetch them usingschema.Type<MyEnum>()
- Fix #181 - Schema builder now correctly respects
SchemaBuilderOptions.IgnoreTypes
. Note it compares names against theType.FullName
- Fix #182 - Add missing dotnet scalar type for
char
. By default this is added as a schema scalar type namedChar
so the client can decide how to handle it. Over the wire it will serialize as a string (default forSystem.Text.Json
). You can change default scalars and mappings by using thePreBuildSchemaFromContext
action when adding your schema
services.AddGraphQLSchema<TContext>(options => {
options.PreBuildSchemaFromContext = schema =>
{
// remove and/or add scalar types or mappings here. e.g.
schema.AddScalarType<KeyValuePair<string, string>>("StringKeyValuePair", "Represents a pair of strings");
};
})
- When generating a field name for the field that takes an ID argument if the name generated matches the current field EntityGraphQL will add
ById
to the field name. E.g. a propertyList<LinePath> Line { get; set; }
previously would try to add theline: [LinePath]
field with no arguments and another field namedline(id: ID!): LinePath
. This causes an error. EntityGraphQL will name addlineById(id: ID!): LinePath
. This is because the singularized version of "line" is "line". - In built field extensions now check if their extra types have already been added by using
Type
instead of name allowing you to add them with your own descriptions etc. - Fix mutations without any mutation arguments would incorrectly include the query context as an argument
InputValue
type was being registered under wrong name #184
- Input Types were incorrectly getting field arguments added when using
AutoCreateFieldWithIdArguments
IDirectiveProcessor
now requires aList<ExecutableDirectiveLocation> On { get; }
to define where the directive is allowed to be used- Removed obsolete
ISchemaType.BaseType
. UseISchemaType.BaseTypes
- Cleaned up
SchemaType
constructors - usingGqlTypeEnum
instead of many boolean flags - Removed obsolete
SchemaProvider.AddInheritedType<TBaseType>
- Removed the instance parameter from
AddMutationsFrom
and friends. Mutation "controllers" are now always created per request like an asp.net controller. Use DI for any constructor parameters - Renamed
ISchemaType.AddBaseType
toISchemaType.Implements
to align with GraphQL languageISchemaType.Implements
will throw an exception if you try to implement a non-interface
- Renamed
ISchemaType.AddAllBaseTypes
toISchemaType.ImplementAllBaseTypes
to align with GraphQL language Create
&FromObject
onSchemaBuilder
now take option classes to configure the create of the schema through reflectionISchemaType.AddAllFields
also takes the option class to configure it's behaviorISchemaType.AddAllFields
default behavior now auto adds any complex types found really reflection the properties & fields and will add those to the schema
- Added new option when building a schema with
SchemaBuilder.FromObject
-AutoCreateInterfaceTypes
. Defaults tofalse
. Iftrue
any abstract classes or interfaces on types reflected with be added as Interfaces in the schema. This is useful if you expose lists of entities on a base/interface type.
ToGraphQLSchemaString
now outputs directives in the schema- #154 - Dynamically generated types used in the expressions now include the field name the type is being built for to aid in debugging issues
- #146 - Allow GraphQL mutation arguments as separate arguments in the method signature. Avoiding the need to create the mutation argument classes. e.g.
[GraphQLMutation]
public Person AddPersonSeparateArguments(string name, List<string> names, InputObject nameInput, Gender? gender)
{
// ...
}
[GraphQLMutation]
public Person AddPersonSingleArgument(InputObject nameInput)
{
// ...
}
Turn into
type Mutation {
addPersonSeparateArguments(name: String, names: [String!], nameInput: InputObject, gender: Gender): Person
addPersonSingleArgument(nameInput: InputObject): Person
}
- #160 - Nested data annotations for validation is now supported
- Main
EntityGraphQL
package now targetsnet6.0;net5.0;netstandard2.1
- #170 - EntityGraphQL now replaces query context expressions in service fields by matching the expression instance it extracted. This allows for more complex expressions when passing data to a service field
- Added support for @oneOf Input Types. Mark an input type with
GraphQLOneOfAttribute
and EntityGraphQL will mark the type with@oneOf
in the schema and validate the input meets the requirements on execution
- #171 inheritance support for nested properties / conditional fields
- #176 - allow fully qualified enums in the filter query language
- Fix #159 - SchemaBuilder will no longer try to create schema fields for
const
fields on mutation args or input types
- #163 - Fix to handle null property in a nested object when processing a System.Text.Json deserialised query document
- #164 - Fix to support inline fragments in a fragment
- #166 - Add missing
!=
operator in the filter expression language and make sure precedence is correct for logic operators
AddMutationsFrom
now can use theServiceProvider
instance to create the mutation class allowing dependency injection at the constructor level like Controllers.- You can still provide an instance of the mutation class that will be used instead which is the same behavior as previous, however this method is considered obsolete and will be removed in a future version. We suggest you utilse the ServiceProvider to register your mutation classes with your desired lifetime.
- Allow types to inherit from multiple base classes/interfaces
- Cleanup SchemaType to use an enum instead of lots of boolean type variables. Previous constructor is obsolete
- Cleanup Interfaces api - added a
AddAllBaseTypes
,AddBaseType
andAddBaseType(string)
which provides a lot more flexibility. See updated docs - Added support for Inline Fragments for types that have interfaces
ToGraphQLSchemaString
now orders types and fields by name for consistency regardless of order of fields added and to reduce differences when diffing the schema
- Fix #120 - Error when using
schema.RemoveTypeAndAllFields
and a field of the removing type had a type that has not been added to the schema - Fix #143 - Error building a null check expression in certain cases.
FromObject
/ default schema generator now adds single fields within non root-level fields. E.g. if a root-level field is a list ofpeople
and each person has a list ofprojects
(and projects has an id) is will create a field onproject(id)
field on person- Add support for nullable reference types - meaning the correct GraphQL schema nullable definitions are generated. @bzbetty
- Fix generation of singular field with
id
arguments on list fields that use a paging extension when generating a schema. @bzbetty - Fix - when adding Mutation argument types only search for public instance properties. @breyed
- Fix interface query introspection. @bzbetty
- Fix #137 - multiple line endings were used in the schema output
- Fix - make sure we use an array for arguments when expected instead of a list<>
- Fix null exception in service field from an object field
- Fix #123 do not output types with no fields in the schema definition
- Fix issue calling
ToList
in an expression that then used aIQueryable
FirstOrDefault
or friends. Resulting in an invalid expression at runtime
- Fix - Throw an error if your query document defines a non-null variable and a null value is supplied
- Service fields that return a list of items are now wrapped in a null check expression like service fields that return a single object are
- Fix - Object fields not included in the schema could be returned when the selection set was missing from the query. Now missing selection sets on list or object fields in queries throw an error. Selection sets are required in graphql queries for non scalar/enum field types. Thanks @breyed
- Fix - issue with a field using a static member e.g. DateTime.MaxValue
- Fix - issue where a nullable value was incorrectly being called
- Added support for interfaces - thanks @bzbetty
- Added
EntityGraphQLException
- use this to throw exceptions and add more error data to the error result via extensions GraphQLValidator
now supports adding custom data via the extensions fieldResolveWithService
methods will throw an exception if the expression returnsTask
as we need the result. Use.GetAwaiter().GetResult()
. Expression do not supportasync
/await
as it is a compiler feature and we need the actual result to build the expression and return the data- Fix using QueryFilter with an empty string treats it as no value - i.e. no filter
- Fix - the type of an array variable defined as required
[Type!]!
was incorrectly reflected - Fix - service type's field used in a field's expression was not being extracted into the select. E.g. service field
User.project
has an expression requiring theuser.id
which is not included in the GraphQL query.
- Fix thread safety issue with cached queries
- Fix support for using arrays in field argument definitions
- fix regression where non-required (nullable) document variables would be set their non-nullable default value. E.g.
Guid
- Fix regression where non service fields in service fields were not being pulled forward to the stage one expression execution.
- Fix regression where services were not be passed to a mutation with no arguments
- Interface for Field Extensions now are passed a flag telling the extension if this is pre or post the call with service fields
GetExpression
in Field Extensions is passed the parent IGraphQLNode - useful when your extension changed the original shape of the object graph, like the paging extensionsservices.AddGraphQLSchema
adopts a more ASP.NET styleoptions
callback overload to configure the creation of the schemaMapGraphQL
implementation now returns400
Bad Request status code if the query results contains errors, as a bad query was sent- Directive interface for building custom directives has changed
UseSort
field extension now takes an array ofSortInput<T>
so order of sorts is used- Parsing floats/doubles/decimals now uses
CultureInfo.InvariantCulture
Clean up on the schema building APIs to make them more consistent, documented and concise - Fix #89 - Remove JSON.NET dependency - This means internally if EntityGraphQL hits a
JObject
orJToken
it does not know what to do with them. Make sureQueryRequest.Variables
are fully deserialized. I.e. do not have anyJObject
/JToken
s in there. Deserialize them to nestedDictionary<string, object>
.
If you use the EntityGraphQL.AspNet package and the MapGraphQL()
method you do not need to worry about anything. EntityGraphQL.AspNet uses System.Text.Json
and handles the nested JsonElement
s with a custom type converter.
If you are directly using SchemaProvider.ExecuteRequest()
(i.e. from a Controller or elsewhere), and you are using Newtonsoft.Json
to deserialize the incoming QueryRequest
you can add a custom converter to your schema to handle nested JObject
/JToken
s when encountered in query variables.
schema.AddCustomTypeConverter(new JObjectTypeConverter());
schema.AddCustomTypeConverter(new JTokenTypeConverter());
See the serialization tests for an example.
- Remove the
WithService()
method used inside a field expression and replace it withResolveWithService<TService>()
on the field for easier discovery in your IDE. Example
schema.Type<Person>().AddField("age", "A persons age")
.ResolveWithService<AgeService>(
(person, ageService) => ageService.GetAge(person.Birthday)
);
- Clean up of
SchemaType
APIs to add/replace/remove fields.- Remove
SchemaProvider.Add/ReplaceField
methods.- Use
SchemaProvider.Query().Add/ReplaceField()
orSchemaProvider.UpdateQuery(queryType => {})
to make changes to the root Query type in the schema
- Use
- Additions to the
Field
API to add more uncommon functionality to chaining methods - Remove
SchemaProvider.UpdateQueryType()
, useSchemaProvider.UpdateQuery(type => {})
- Remove
SchemaProvider.TypeHasField()
- Remove
SchemaProvider.GetQueryFields()
- useSchemaProvider.Query.GetFields()
- Renamed
GetGraphQLSchema()
toToGraphQLSchemaString()
- Renamed
AddMutationFrom()
toAddMutationsFrom()
- Removed Obsolete methods:
RequiresAllClaims
replaced byRequiresAllRoles
RequiresAnyClaim
replaced byRequiresAnyRole
ExecuteQuery
replaced byExecuteRequest
ExecuteQueryAsync
replaced byExecuteRequestAsync
- Remove
- Support for persisted queries (enabled by default) - https://www.apollographql.com/docs/react/api/link/persisted-queries/
- Support for a query cache of recent queries. Enabled by default. Caches the result of compiling the query document string to an AST. Execution is then applying the document level variables, building the expressions then execution
- Better support for nested objects in
QueryVariables
- Performance enhancements when building internal types for arguments
- Performance of compiling and building expressions has been improved - it is about 2 times faster. Note this is just building the expressions, not executing them which triggers your services/EF/etc
- Reduction in memory allocation when compiling queries by around 30%
- You can no add/define mutation methods as delegates/anonymous functions etc.
- You can now use
[Range]
&[StringLength]
attributes on your arguments for more validation options - Introduced custom argument validators - a simple way to act on field arguments before execution. Great for custom/complex input validation on arguments. Use
field.AddValidator()
or theArgumentValidatorAttribute
attribute. - Using
AddAllFields(true)
on anInputType
will add the sub-complex class types asInputType
s as well - New option to auto add other classes found on mutation arguments as
InputType
s when adding a mutation
- Fix - Paging field extensions are now thread safe to support multiple different queries being run on the same field at the same time
- Fix #101 - allow custom de/serialization of incoming requests and outgoing responses, via. services
IGraphQLRequestDeserializer
&IGraphQLResponseSerializer
.- Note that the objects created in the resulting
QueryResult
have fields named like the fields in the schema which is controlled by thefieldNamer
function provided to theSchemaProvider
which defaults to GraphQL "standard" (fields camelCase, types PascalCase)
- Note that the objects created in the resulting
- Fix field name looks up that were not using the
fieldNamer
function inSchemaProvider
- Fix bug where compiler would loop through all available arguments even if it already found the matching type
- Fix argument types of unsigned short/int/long
- Fix #72 - Handling dictionaries introspection - note it will try to create a scalar type
KeyValuePair<T1, T2>
in the schema by default - Fix handling argument types of unsigned short/int/long
- Fix issue parsing float/double argument values
- Fix null exception with mutations returning a selection with a list field
- Fix directives on mutation fields
- Fix #110 - Field using the wrong sort input object when the fields are the same
- Fix #99 issue using the MapGraphQL() extension method
- New option to disable introspection. Use
introspectionEnabled
parameter when creatingSchemaProvider
. Defaults totrue
.
- Fix #96 - processing int/long/short as list arguments in mutations - thanks @pierrebelin
- Fix #92 - error processing mutation arguments that are lists/arrays
- Authorization now supports using ASP.NET policies from the
EntityGraphQL.AspNet
packageIAuthorizationService
is resolved to check authorization and needs to be registered[Authorize]
attribute can be used instead of the[GraphQLAuthorize]
attribute when usingEntityGraphQL.AspNet
- Fix -
RequiredAttribute
results in the field being not null in the generated GraphQL Schema - Fix - Schema introspection was incorrectly returning
__typename
for Enums UseConnectionPagingAttribute
takes optional arguments for default page size and max page sizeUseOffsetPagingAttribute
takes optional arguments for default page size and max page sizeEntityGraphQL.AspNet
now uses System.Text.Json for de/serialization internally. It still supports JSON.NET objects in the variable object (as well as System.Text.Json types)- Fix #19 - you can mark fields (including mutations) as deprecated using the dotnet
[Obsolete]
attribute or theIField.Deprecate(reason)
method in the schema building - Fix #88 - If an argument is marked as required and not provided in the query request an error is raised. Mark arguments optional via the API, or make it a nullable type or give it a default value
- Query used in ConnectionPaging now resolves itself using
.ToList()
RequireAnyClaim()
&RequireAllClaims()
. UseRequireAnyRole()
&RequireAllRoles()
as theClaimTypes.Role
was used previously and this change makes it explicitschema.ExecuteQueryAsync/ExecuteQuery(QueryRequest, TContextType, IServiceProvider, ClaimsIdentity, ExecutionOptions)
. Use theExecuteRequest
/ExecuteRequestAsync
methods that take the fullClaimsPrincipal
as we now support authorization with policies
- Fix #86. Mutations not correctly checking required authorization on the mutation field directly
- Fix -
RequiredAttribute
results in the field being not null in the generated GraphQL Schema - Fix issue with expressions failing in a high throughput, threaded use case (heavily hit API)
- Fix issue passing optional enum arguments
- New extension methods to ease adding your schema to the service collection. See docs -
services.AddGraphQLSchema<DemoContext>(options => {})
- New package EntityGraphQL.AspNet with extensions to easily expose a graphql endpoint with
MapGraphQL<T>()
.
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQL<DemoContext>();
});
- Fix issue reconnecting from a service field to the context
- Fix issue when execution is split across non service fields and then with service fields and the first result is null
- Fix issue using Connection/Offset paging on collection fields that were not on the query root
- Fix issue using Connection/Offset paging on collection fields that have service fields
- Option to add default sort when using
UseSort()
field extension
- Introduction of fields extensions to encapsulate common field logic and apply it to many fields. See update docs. New built in field extensions
UseConnectionPaging()
which when applied to a collection field modifies the field to implement the GraphQL Connection spec for paging data with metadataUseOffsetPaging()
which when applied to a collection field modifies the field to implement an offset style paging structureUseFilter()
which when applied to a collection adds afilter
argument that takes an expressionUseSort()
which when applied to a collection adds asort
arguments that takes fields to sort the collection by
- Replaced Antlr based GraphQL query lexer/parser with HotChocolate.Language Parser. Parsing of query documents is much faster!
- You can now directly use lists (
[12,32]
, etc) and objects ({name: "Frank"}
) as arguments in the query document. Although it is still recommended to use theVariables
in the query - Added benchmarks to help explore performance issues in expression building (What we do with expressions is fast, but found the Antlr Parser was slow)
- Directives now supported on fragment spreads
Breaking changes
- EntityGraphQL now targets netstandard2.1
- Some optional arguments in
ExecuteQuery
moved to an Options object
- New docs https://entitygraphql.github.io/introduction
- Added
SchemaProvider.UpdateType<T>(Action<SchemaType<T>> updateFunc)
to better help "contain" schema types. Instead of
schema.Type<MyType>().AddField(...);
schema.Type<MyType>().AddField(...);
schema.Type<MyType>().AddField(...);
we have
schema.UpdateType<MyType>(t => {
t.AddField(...);
t.AddField(...);
t.AddField(...);
});
Similar for SchemaProvider.AddType<T>(string name, string description, Action<SchemaType<T>> updateFunc)
- You can pass a
ILogger<SchemaProvider<T>>
when creating aSchemaProvider
. Exceptions etc. will be logged - Added
Take<TSource>(this IQueryable<TSource> source, int? count)
that works onIQueryable<T>
to support EF translation
Breaking changes
- EntityGraphQL now targets netstandard2.0
- Big refactor/clean - hopefully easier to follow the post Antlr (compiled graphql) output - see
GraphQL*Field
classes - Support for dotnet Entity Framework Core 3.1+ when using other services in the schema (
WithService()
) - Removed the
Where<TSource>(this IEnumerable<TSource> source, EntityQueryType<TSource> filter)
helper. Use theWhereWhen
methods that supportEntityQueryType
To support EF 3.x as a base schema context we now build and execute expressions in 2 stages. See the updated readme section How EntityGraphQL handles WithService().
- Update Humanizer.Core dependency which resolves issue with newer dotnet core
- Fix issue where
FieldNamer
was not being consistently used. Thanks @AnderssonPeter - Make sure we include inner exceptions on errors. Thanks @AnderssonPeter
- Added string and long parsing for DateTime and DateTimeOffset. Thanks @GravlLift
- As per GraphQL spec commas are optional (previously EntityGraphQL expected them in field/mutation arguments)
Breaking changes
- errors property on query result should not be present on the response if there are no errors per the graphQL specification.
- Fix bug with using
WithService()
when you require the schema context service again to create a link between services
- When using services other than the schema context in fields (that return a single object not a Enumerable) the methods/services are no longer executed multiple times. (issue #36). Notes below
- When a string matches a date time it will be converted to a
DateTime
object. Useful when using theArgumentHelper.EntityQuery
for advanced filtering. Regex matches"yyyy-MM-dd HH:mm:ss.fffffffzzz"
,"yyyy-MM-dd HH:mm:ss"
,"yyyy-MM-dd"
with the separator between date and time being eitherT
EntityQueryCompiler
(used inArgumentHelper.EntityQuery
) supports EnumsfieldNamer
used in mutations too
Breaking changes
- Cleaning up the API. The optional
isNullable
argument is removed from theAddField()
methods. UseIsNullable(bool)
method on theField
class or the[GraphQLNotNull]
attribute. - Cleaning up the API.
fieldNamer
argument removed from methods inSchemaProvider
andSchemaType
. Pass in afieldNamer
func to the constructor ofSchemaProvider
which will be used when it is auto creating fields. If you pass it in viaSchemaBuilder.FromObject
it will set it on theSchemaProvider
created. AddCustomScalarType()
removed. Previously marked as obsolete. UseAddScalarType()
If you build a field like so
schema.AddField("myField", ctx => WithService((IMyService srv) => srv.DoSomething(ctx)));
// Register the service with DI somewhere
public class MyService: IMyService {
public SomeObject DoSomething(Context ctx)
{
// do something
return data;
}
}
With a query like
{
myField { field1 field 2 }
}
We use to build an expression like so
srv.DoSomething(ctx) == null ? null : new {
field1 = srv.DoSomething(ctx).field1,
field2 = srv.DoSomething(ctx).field2
}
We now wrap this in a method call that only calls DoSomething(ctx)
a single time Which looks like this
(ctx, srv) => NullCheckWrapper(srv.DoSomething(ctx), parameterValues, selection); // simplifying here
// Again a simified example of what NullCheckWrapper does
public object NullCheckWrapper(Expression<Func<Context, IMyService>> baseValue, object[] values, LambdaExpression selection)
{
// null check
if (baseValue == null)
return null;
// build the select on the object
var result = selection.Compile().DynamicInvoke(baseValue);
}
This works with services used deeper in the graph too. Example
schema.Type<Person>().AddField("complexField", (person) => DoSomething(person.Id));
GraphQL
{
people {
complexField {
field1
field1
}
}
}
The wrapped expression looks like this
(ctx, srv) => ctx.People.Select(person => new {
complexField = NullCheckWrapper(srv.DoSomething(person.Id), parameterValues, selection); // simplifying here
})
This has been tested with EF Core and works well.
- You can now secure whole types in the schema. Add the
[GraphQLAuthorize("claim-name")]
to the class or useschema.AddType(...).RequiresAllClaims("some-claim")
,schema.AddType(...).RequiresAnyClaim("some-claim")
- Add
GetField(Expression<Func<TBaseType, object>>)
overload - operation name is optional for a
query
operation as per GraphQL spec if it is the only operation in the request - Breaking - removed the
authorizeClaims
argument fromAddField()
. Please usefield.RequiresAllClaims("some-claim")
,field.RequiresAnyClaim("some-claim")
- Change - descriptions generated for a
.graphql
schema file now use the multiple line triple-quote"""
- Fix issue where an
WithService()
expression is wrapped in aUnaryExpression
and we fail to get the lambda
- Expose a
SchemaProvider.ExecuteQueryAsync()
- Fix #53 support mutations with no arguments
- With the above fix the context and/or the mutation arguments parameters are optional in your mutation method
- the parameters in the mutation methods are no longer required to follow a position
SchemaProvider.AddCustomScalarType()
is deprecated, useAddScalarType
- Directvies are now included in schema introspection
- Fix #52 - sometimes incorrect types generated for schema introspection or the GraphQL schema file format
- Refactor type information held in the schema. This mean return types etc are evaluated at schema creation time not execution. If you add a field that requires a type as an Argument or return type, that type must already be in the schema
- You can now provide a field namer function to name the generated fields when using
SchemaBuilder.FromObject()
,ISchemaType.AddAllFields()
orSchemaProvider.PopulateFromContext()
Breaking changes
- The class that represents the mutation arguments must be marked with the
MutationArgumentsAttribute
either at the class level or the parameter SchemaProvider
now adds a defaultDate
scalar type in the schema that maps to/from the C#DateTime
class. If you were previously adding that you'll get an error on type existing. UseSchemaProvider.RemoveType<DateTime>()
to remove it and add it with a different name- Type mapping information (
AddTypeMapping()
) are evaluated at schema creation time. You may need to add mappings before creating the rest of your schema
- Removed the empty
IMutationArguments
in favor for aMutationArgumentsAttribute
on the parameter or the class
- Support async mutation methods
- Add model validation for mutation arguments. See updated readme
- Fix issue with services not correctly being included when the field is used in a fragment
- Add support for directives. Supported by default are
@include(if: Boolean!)
and@skip(if: Boolean!)
. You can add your own that make changes to the expression pre-execution - Added syntax support for subscription queries (they compile/no error but do not execute or work)
- Removed support for older syntax of complex queries that is not GQL standard
- Refactored
GraphQLVistor
and friends to make it easier to follow what is happening (I hope). See CONTRIBUTING.md for some notes - From my testing the compiling and expression building is 15-20% faster than before (still network and or the DB calls are the largest)
- Allow
enum
values in the query schema (e.g. as an argument) - Ignore static properties & fields on the object passed to
SchemaBuilder.FromObject
- they were not supported and threw errors anyway
- Name all
ParameterExpression
s as EF 3.1 expects a name (can throw an error)
- Fix claims check when required claims are empty
- Fix error message state which claims are required for the given access error
- Sorry about the quick turn around
- Breaking changes
- Using DI inspired design now instead of the
TArg
- Use
WithService
helper to let EntityGraphQL know which services you require e.g. in anAddField
use(db, p) => WithService<IUserProvider>(users => users.Load(p.id))
- For mutations just add the services as arguments (at the end) as you typically do in dotnet
schema.ExecuteQuery()
takes anIServiceProvider
which it uses to look up required services likeIUserProvider
above
- Using DI inspired design now instead of the
- Breaking changes
- Trying to clean up the interface for creating a schema and allowing an easier way to get services in mutations and field selections
- Rename
MappedSchemaProvider
toSchemaProvider
- Remove extension
object.QueryObject()
and require a more specific call toSchmeaProvider.ExecuteQuery()
SchmeaProvider.ExecuteQuery()
takes aTArg
type which is an argument that will be passed to all field selections and mutation methods. This replacesmutationArgs
inobject.QueryObject()
and lets both mutations and field selections access other services non-statically (e.g. viaTArg
being anIServiceProvider
). See updated readme and demo projectSchemaProvider
is now create usingSchemaBuilder.Create<TContext, TArg>()
orSchemaBuilder.Create<TContext>()
giving you a short cut for not providing aTArg
SchemaBuilder.FromObject<TContext, TArg>()
now takes second type argument for theTArg
value. AlsoSchemaBuilder.FromObject<TContext>()
shortcut
- Fix bug where EntityQuery arguments were being cached in the schema
- Add
ContextId
to the ignored list inSchemaBuilder
for EF 3.1
- Clean up
LinqExtensions
, removing the overloads that takeLambdaExpression
s. Use.AsQueryable().Where(someExpressionVar)
instead. It works better with EF and other LinqProviders.
- Breaking change - Multiple
[GraphQLAuthorize]
mean all polices are required and supplying multiple in a single[GraphQLAuthorize]
mean any - Do not generate an empty mutation type if there are no mutations
- Fix query introspection to output mapped types correctly
- Support multiple queries in a request with the operation name of which one to run - e.g. how GraphiQL handles multiple queries
- Update error messages
- Clean up some APIs -
SchemaType.AddAllFields()
,Field.RequiresAllClaims()
,Field.RequiresAnyClaim()
- Initial support for Authorization and Security in the schema - see updated readme and provide feedback
- Support
fragment
statements in other positions in the query
- Fix error with
EntityQueryType<>
as a field argument not being defined as aString
in introspection
- Fix issue introduced in 0.28 when using the
RequiredField<>
type
- Only convert a string matching a
Guid
when the arg type is aGuid
orGuid?
- Fix issue where a non-required EntityQueryType Filter throw an error if it wasn't supplied
- Better support mutations that return an object, not a list
- Introspection query
__type(name: "")
now correctly returns an object not an array [Description("")]
attributes onenum
fields are now read into the schema- Fix issue where introspection query would have duplicate types for enum types
ISchemaType.AddAllFields
requires a schema as it can add newly discovered types to that schemaISchemaType.AddAllFields
by default adds newenum
types to the schema if found as a field typeISchemaType.AddAllFields
can (off by default) add new complex types to the schema if found as a field typeSchema.Type<TType>()
now searches byTType
nottypeof(TType).Name
. Allowing you to add a type with a different name but still get the typedSchemaType<T>
back
- Add the ability to add enum types to the schema
- The auto schema builder now adds enum types it finds to the schema by default
- Enum values are referenced by the string value, if using JSON.NET you will want to use
[JsonConverter(typeof(StringEnumConverter))]
- Add
GraphQLNotNullAttribute
to mark fields as not nullable in the graphql schema - By default when generating a
.schema
fileIEnumerable<T>
will generate the element type as not nullable. E.g.[T!]
. UseGraphQLElementTypeNullableAttribute
to mark it that the list can contain null items - Support mapping
decimal
tonumber
- Better support for defining nullable or non-nullable types
- Allow adding a mapping type to a type that already exists in the schema. E.g. you might add an input type
Point
and want to map the dotnet typePoint
to it.
- fix issue with required type in an array e.g.
[ID!]
- fix issue with generated required types
- Output fields as required in .graphql schemas
- You can now specify if a field is ignored for queries, mutations or both (if you're sharing DTOs/objects)
- Don't output the meta information of the schema in the schema definition
- Prevent duplicate scalar types in schema generation
- Fix issue where
mutation
keyword could not have any white space before it
- Change, make ENUMs a
Int
type as dotnet serialises them like that - Fix input types missing for the SDL schema generated
- Fix issue where mutation args has repeating
ofType
data in introspection - Fix issue where InputTypes would be duplicated in introspection query results
- Fix issue where
ToList()
was being called deep in expressions causing issues with EF
- Add the ability to add custom scalar types to the schema
- Fix a bug where introspection queries were in correct if you have a List/Array in your mutation type
- Fix a bug where mutation arg objects retained values from previous mutation - i.e if the next call to that mutation didn't provide some optional arguments
QueryObject()
callsToList()
on any lists so if you are using something like EF all queries will be evaluated onQueryObject()
, not just the ones that return a single object (as they callFirstOrDefault()
). This is more consistent, the result contains all your data (regardless of underlying ORM or not) and not a miz of evaluated and non-evaluated.- Add
RemoveTypeAndAllFields()
onMappedSchemaProvider
to more easily clean up a schema that was auto created bySchemaBuilder.FromObject<T>()
- Fix case matching of arguments in mutations. EntityGraphQL defaults to turning dotnet
UpperCaseFieldsAndProperties
tocamelCaseFieldsAndProperties
as this was the intention with the change in 0.18.0 - Enum values are as defined. E.g. if you have an enum
Meter
you can use"Meter"
not"meter"
- map Int16 and UInt16 to Int
- Fix issue where argument names were not case sensitive (the Breaking change introduced in 0.18)
- Fix
kind
in schema introspection query to not have!
- Update dependencies (JSON.NET)
- Fix some small casing issues
- Support for schema introspection. Top two fields (
__schema
and__type(name: String!)
) are implemented. There are some things missing where we currently don't support the feature (directives). GraphiQL introspection query executes and you can navigate the example. Big thanks to @JTravis76 for starting the work. - Implement #18 default argument values in GQL operations
mutation MyMutation($arg: String = "hey defaults") { ... }
- Breaking change - If you purely use
SchemaBuilder.FromObject()
it now creates all field nameslowerCaseCamel
and type namesUpperCamelCase
like the GraphQL defaults. Also since GraphQL is case sensitive I have enforced that. You may need to update some queries to match casing
- Add the option to have other parameters passed into a mutation method. Very useful for IServiceProvider or other services your mutations require
- Fix issue where duplicate fields (say from a query and a fragment) would cause an error
- Bring inner exception details up
- Fix issue where fields that require arguments fail (See Paging example in Demo)
- Add support for full queries on a mutation result. See readme for more details (you return an Expression)
- Initial support for GraphQL fragments. fix #2
- Fix issues with using field arguments deeper in the graph schema
- Add support for
operationName
in theGraphQLRequest
- Add support for graphql comments
- Add GraphiQL web interface to the demo app
- Add
GraphQLIgnore
attribute to ignore a field on a Type for the automatic schema builder - fix bug where it would sometimes try to give an
UInt64
to an argument that required anInt32
- (beta) Add
dotnet gql
command to generate a schema from your current DBContext. See readme for more info
- Add
WhereWhen()
to the extension helpers
- Fix bug in handling converting a string into an enum
- Fix issue looking up types internally when working with anonymous types
- Fix issue with incorrectly checking for generic types
- Fix issue with array types in the dynamically generated type for lambdas
- Fix issue where the generated GraphQL schema had the incorrect type for arrays (e.g. double[])
- Fix issue with
SchemaBuilder.FromObject
building invalid types from arrays.
- Fix an issue where it would generate an invalid field name if we couldn't singularize the name
- Move the query results into a
QueryResult
class so it is easier to work with
- Fix #11 - failure to use
RequiredField
with types likeuint
- it would try to initialise it with anint
- Remove old code that supported multiple fields with the same name and different arguments. GraphQL doesn't support that and it caused a bug where it would sometimes not find the field you want. You can implement optional arguments and build a complex field like
schemaProvider.AddField("myField", new {name = (string)null, id = (Guid?)null}, (db, param) => param.id.HasValue ? db.MyEntities.Where(l => l.Id == param.id).FirstOrDefault() : db.MyEntities.Where(l => l.Name == param.name).FirstOrDefault(), "Returns an Entity object by ID or a match on the name argument");
- Allow user to supply a type mapping for the generated GraphQL schema
- Fix an issue where we would some time identify a type as IEnumerable when it shouldn't have been
- Allow
ReplaceField
on a sub type
- Convert enums correctly
- Fix SchemaGenerator to support arrays better
- Support turning
QueryRequest
variables from JSON objects into their required objects
- Bring back
ReplaceField
as technically GraphQL doesn't support overloading, so if you're using tools like Apollo etc to generate code you need to only have unique fields - Added
GetGraphQLSchema
on the schema to return a.graphql
schema file for input into tools like Apollo codegen - Add the option to add descriptions to Mutations
- Fix issue where operation name with no arguments failed
- Breaking change: Strings are now defined by double quotes
"
to fit in with GraphQL better - Added support to use a LINQ-style language as a argument in GraphQL. E.g the following GQL field,
{ users(filter: "active = true and age > 20") { id name } }
can be defined withschema.AddField("users", new {filter = EntityQuery<User>()}, (ctx, p) => ctx.Users.Where(p.filter), "Return filtered users")
. Letting you write that filter using any fields defined on theUser
object - Add
null
/empty
constant for checking for null in EQL
- Fix bug converting Int values to double? values
- Support field "overloads" - fields with same name and different arguments.
- Renamed package EntityGraphQL to emphasizes that it implements GraphQL
- Fix issue with arrays and objects in variables parameter on the request
- Better error messages when GraphQL arguments can't be mapped to an object
- Validate required variables in operations are supplied in the variables dictionary
- Fix potential issue with selecting sub object graphs
- Change the errors to appear in
errors
key along sidedata
key as per GraphQL - Fix an issue when selecting fields from a mutation result
- Support selecting an object that may be null
{ person {name} }
person
will be null if it does not exist
- Parameter types can be optional (no
!
)
- Fix type issues with mutation args
- Change auto entity call with
id:
(e.g.{ entity(id: 13)}
) to call theFirst()
method last - Fix issue with selecting a one-to-one relation in a query
- Fix a issue where schema and method provider were not being passed down in
QueryObject
- Add initial support for Mutations
,
between fields is optional like in GraphQL- Support
__typename
metadata
Moved EntityQueryLanguage.DataApi
namespace toEntityQueryLanguage.GraphQL
to better communicate that its intent is to support- Add support GraphQL arguments in fields. See updated readme
- By default
SchemaBuilder.FromObject<TType>()
generates a non-plural field for any type with a publicId
property, with the argument name ofid
. E.g. A fieldpeople
that returns aIEnumerable<Person>
will result in aperson(id)
field - Move results to field
data
in the resulting object to match GraphQL - Support the
query
keyword for graphql
- Added support for complex nested queries when using the
EFRelationshipHandler
- Fix type caching issue causing exception on changing a sub query