Open wtorricos opened 2 years ago
Most likely you need to call FieldAsync
rather than Field
for some of your field definitions.
I'd further guess that the field type in this case is an interface or union, and what happened is that IsTypeOf returned false for the Task<T>
returned value, causing the type to be null. With this change here in proposed PR graphql-dotnet/graphql-dotnet#3270 : https://github.com/graphql-dotnet/graphql-dotnet/pull/3270#discussion_r939766433 the code will use the interface type and not cause a null reference exception. Then you would at least see a better exception than what is seen currently, but it would not solve your issue.
Without seeing more of your code, this is just a guess, of course.
Thank you for the reply.
Regarding FieldAsync
, I don't think that's the problem as even some really simple types are failing, we have many like the one below:
public sealed class CharacterType : AsyncNodeGraphType<CharacterModel>
{
public CharacterType()
{
Name = "Character";
Id(characterModel => characterModel.Id);
Field<NonNullGraphType<StringGraphType>>()
.Name("name")
.Resolve(context => context.Source.Name ?? "None");
}
public override async Task<CharacterModel> GetById(IResolveFieldContext<object> context, string id)
{
var characterService = context.RequestServices.GetRequiredService<CharacterService>();
Guid characterId = Guid.Parse(id);
return characterService.GetByIdAsync(characterId, context.CancellationToken);
}
}
The workaround that is working at the moment is to extend NodeGraphType
instead of AsyncNodeGraphType
Right I see. AsyncNodeGraphType<T>
(which is in the relay project) inherits from NodeGraphType<Task<T>>
, and when you call Id
it calls Field
instead of FieldAsync
. The relay project's AsyncNodeGraphType
needs to be fixed so that it does not call Field
but instead calls FieldAsync
.
See faulty code here: (when used by the derived AsyncNodeGraphType
-- the code is fine as NodeGraphType
)
There's nobody that actively works on this project, but if you'd like to open a pull request @tico321 I would be happy to review it, and when merged, issue an updated release.
Thank you for the fast response, I'll try to take a look over the weekend
Supporting NodeGraphType
as well as AsyncNodeGraphtype
seems to be a little bit trickier than what I thought, using FieldAsync wan't enough, but I found that awaiting the result in QueryGraphType
fixes the problem. https://github.com/graphql-dotnet/relay/blob/7e5d8e4a6365194b68f282239b31f36137ace5aa/src/GraphQL.Relay/Types/QueryGraphType.cs#L24
Since I'm only using AsyncNodeGraphType
I'm going to use the following class in my project until I can find a way to make it work with both Node and AsyncNode.
public class AsyncQueryGraphType : ObjectGraphType
{
public AsyncQueryGraphType()
{
Name = "Query";
Field<NodeInterface>()
.Name("node")
.Description("Fetches an object given its global Id")
.Argument<NonNullGraphType<IdGraphType>>("id", "The global Id of the object")
.ResolveAsync(ResolveObjectFromGlobalId);
}
private async Task<object> ResolveObjectFromGlobalId(IResolveFieldContext<object> context)
{
var globalId = context.GetArgument<string>("id");
var parts = Node.FromGlobalId(globalId);
var node = context.Schema.AllTypes[parts.Type];
var getById = node!.GetType().GetMethod("GetById");
dynamic awaitable = getById!.Invoke(node, new object[] { context, parts.Id });
await awaitable!;
return awaitable.GetAwaiter().GetResult();
}
}
Having said that please let me know if you have any suggestions that may work and I'll take a look when I have some time.
I found that when implementing
AsyncNodeGraphType
theExecutionStrategy
class will throw anInvalidOperationException
since the following call returns null: https://github.com/graphql-dotnet/graphql-dotnet/blob/ed720f46e26704ed457b723801637d9d726f45bd/src/GraphQL/Execution/ExecutionStrategy.cs#L636The problem seems to be that the execution strategy is not awaiting the result and is trying to find the GraphType of Task instead of just T.
Our implementation broke after we upgraded GraphQL, here you can see the version of our packages:
Hope this gives you enough information to fix it