Getting AutoRegisteringInputObjectGraphType and AutoRegisteringObjectGraphType working for GraphQL.NET v5

1k views Asked by At

I'm trying to get the auto registering functionality working in GraphQL.NET. However getting some issues with List types. Please note that I'm very new to the world of GraphQL and have never used this framework before, if you see any improvements to the code, please let me know. Appreciate any help with this.

The following error message is received.

"Message": "The GraphQL type for field 'BasicInformationResponse.status' could not be derived implicitly. Could not find type mapping from CLR type 'ScroW.Application.Features.Information.Queries.BasicInformation.Status' to GraphType. Did you forget to register the type mapping with the 'ISchema.RegisterTypeMapping'?",

I have registered the following Schema and Types. Please note that BasicInformationResponse contains a List of statuses as per below.

    public class BasicInformationResponseType : AutoRegisteringObjectGraphType<BasicInformationResponse>
    {
        public BasicInformationResponseType() : base()
        {
            Name = "BasicInformationResponseType";
        }
    }
    
    public class StatusType : AutoRegisteringObjectGraphType<Status>
    {
        public StatusType() : base()
        {
            Name = "StatusType";
        }
    }

    public class BasicInformationResponse
    {
        public string OrganizationNumber { get; set; }
        public string Name { get; set; }
        public List<Status> Status { get; set; }
    }

Not sure what kind of field I'm registering here? (rn as a StringGraphType, but I'm pretty sure it should be something else).

    public class Query : ObjectGraphType
    {
        public Query(IMediator mediator)
        {
            FieldAsync<StringGraphType>(
                Name = "basicInformation",
                arguments: new QueryArguments(new QueryArgument<AutoRegisteringInputObjectGraphType<BasicInformationResponse>> { Name = "organizationNumber" }),
                resolve: async x =>
                {
                    return await mediator.Send(new BasicInformationQuery
                    {
                        OrganizationNumber = x.GetArgument<String>("organizationNumber")
                    });
                });
        }
    }

My schema definition

    public class ScroWSchema : Schema
    {
        public ScroWSchema(IServiceProvider provider)
            : base(provider)
        {
            Query = (Query)provider.GetRequiredService(typeof(Query)) ?? throw new InvalidOperationException();
            // Mutation = (StarWarsMutation)provider.GetService(typeof(StarWarsMutation)) ?? throw new InvalidOperationException();

            // FieldMiddleware.Use(new InstrumentFieldsMiddleware());
        }
    }

And lastly startup. I'm not really sure around what is needed to be registered as a singleton and not and was confused by different guides out there. If any can be removed please let me know.

            services.AddGraphQL(builder => builder
                // .AddSchema<ScroWSchema>()
                .AddSelfActivatingSchema<ScroWSchema>()
                .AddClrTypeMappings()
                .AddNewtonsoftJson()
                .AddGraphTypes(typeof(ScroWSchema).Assembly)
            );
            services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
            services.AddSingleton<IGraphQLSerializer, GraphQLSerializer>();
            services.AddSingleton<ISchema, ScroWSchema>(services => new ScroWSchema(new SelfActivatingServiceProvider(services)));
            services.AddSingleton(typeof(AutoRegisteringObjectGraphType<>));
            services.AddSingleton(typeof(AutoRegisteringInputObjectGraphType<>));
            services.AddSingleton<BasicInformationResponseType>();
            services.AddSingleton<StatusType>();
1

There are 1 answers

0
Rickard Marjanovic On BEST ANSWER

Alright, so managed to solve this with a lot of trial and error etc.

In general, the AutoRegisteringObjectGraphType was correctly setup:

    public class BasicInformationResponseType : AutoRegisteringObjectGraphType<BasicInformationResponse>
    {
        public BasicInformationResponseType()
        {
        }
    }

Scema was also correct:

    public class ScroWSchema : Schema
    {
        public ScroWSchema(IServiceProvider provider)
            : base(provider)
        {
            Query = (Query)provider.GetRequiredService(typeof(Query)) ?? throw new InvalidOperationException();
        }
    }

Issue was the Query class, which wasn't correctly setup, the below got it working:

    public class Query : ObjectGraphType
    {
        public Query(IMediator mediator)
        {
            FieldAsync<BasicInformationResponseType>(
                Name = "basicInformation",
                arguments: new QueryArguments(new QueryArgument<NonNullGraphType<StringGraphType>> { Name = "organizationNumber" }),
                resolve: async x =>
                {
                    return await mediator.Send(new BasicInformationQuery
                    {
                        OrganizationNumber = x.GetArgument<string>("organizationNumber")
                    });
                });
        }
    }

In regards to startup services were automatically added through the GraphQL registration, no need to add specific services.

            services.AddGraphQL(builder => builder
                .AddSelfActivatingSchema<ScroWSchema>()
                .AddClrTypeMappings()
                .AddSystemTextJson()
                .AddGraphTypes(typeof(ScroWSchema).Assembly)
            );