Wasyster
Wasyster

Reputation: 2535

ASP.NET CORE Hot Chocolate query error for nested object

I am learning how to write GraphQL in asp.net core 5 project. I am using Hot Chocolate v5 and got an error when executing the following query:

query
{
  platform
  {
    id
    name,
    commands
    {
      id
      howTo
      commandLine
    }
  }
}

Executing this query I got the following error: { "errors": [ { "message": "There was no argument with the name platform found on the field commands.", "locations": [ { "line": 7, "column": 5 } ], "path": [ "platform", 4, "commands" ], "extensions": { "fieldName": "commands", "argumentName": "platform" } }, ...

If I execute the query where there the following queries then its working:

query
{
  platform
  {
    id
    name
  }
}

query
{
  command
  {
    id
    howTo
    commandLine
  }
}

My code fragments that I think is relevant for this error are:

public class Command
    {
        /// <summary>
        /// Represents the unique ID for the command.
        /// </summary>
        [Key]
        public int Id { get; set; }

        /// <summary>
        /// Represents the how-to for the command.
        /// </summary>
        [Required]
        public string HowTo { get; set; }

        /// <summary>
        /// Represents the command line.
        /// </summary>
        [Required]
        public string CommandLine { get; set; }

        /// <summary>
        /// Represents the unique ID of the platform which the command belongs.
        /// </summary>
        [Required]
        public int PlatformId { get; set; }

        /// <summary>
        /// This is the platform to which the command belongs.
        /// </summary>
        public Platform Platform { get; set; }
    }

public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions options) : base(options)
        {
        }

        public DbSet<Platform> Platforms { get; set; }
        public DbSet<Command> Commands { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Platform>()
                   .HasMany(x => x.Commands)
                   .WithOne(x => x.Platform!)
                   .HasForeignKey(x => x.PlatformId);

            builder.Entity<Command>()
                   .HasOne(x => x.Platform)
                   .WithMany(x => x.Commands)
                   .HasForeignKey(x => x.PlatformId);
        }
    }

[GraphQLDescription("Represents the queries available.")]
    public class Query
    {
        /// <summary>
        /// Gets the queryable <see cref="Command"/>.
        /// </summary>
        /// <param name="context">The <see cref="AppDbContext"/>.</param>
        /// <returns>The queryable <see cref="Command"/>.</returns>
        [UseDbContext(typeof(AppDbContext))]
        [UseFiltering]
        [UseSorting]
        [GraphQLDescription("Gets the queryable command.")]
        public IQueryable<Command> GetCommand([ScopedService] AppDbContext context)
        {
            return context.Commands;
        }

        /// <summary>
        /// Gets the queryable <see cref="Platform"/>.
        /// </summary>
        /// <param name="context">The <see cref="AppDbContext"/>.</param>
        /// <returns>The queryable <see cref="Platform"/>.</returns>
        [UseDbContext(typeof(AppDbContext))]
        [UseFiltering]
        [UseSorting]
        [GraphQLDescription("Gets the queryable platform.")]
        public IQueryable<Platform> GetPlatform([ScopedService] AppDbContext context)
        {
            return context.Platforms;
        }

public class PlatformType : ObjectType<Platform>
    {
        protected override void Configure(IObjectTypeDescriptor<Platform> descriptor)
        {
            descriptor.Description("Represents any software or service that has a command line interface.");

            descriptor.Field(p => p.Id)
                      .Description("Represents the unique ID for the platform.");

            descriptor.Field(p => p.Name)
                      .Description("Represents the name for the platform.");

            descriptor.Field(p => p.LicenceKey)
                      .Ignore();

            descriptor.Field(p => p.Commands)
                      .ResolveWith<Resolvers>(p => p.GetCommands(default!, default!))
                      .UseDbContext<AppDbContext>()
                      .Description("This is the list of available commands for this platform.");
        }

        private class Resolvers
        {
            public IQueryable<Command> GetCommands(Platform platform, [ScopedService] AppDbContext context)
            {
                return context.Commands.Where(p => p.PlatformId == platform.Id);
            }
        }

public class CommandType : ObjectType<Command>
    {
        protected override void Configure(IObjectTypeDescriptor<Command> descriptor)
        {
            descriptor.Description("Represents any executable command.");

            descriptor.Field(c => c.Id)
                      .Description("Represents the unique ID for the command.");

            descriptor.Field(c => c.HowTo)
                      .Description("Represents the how-to for the command.");

            descriptor.Field(c => c.CommandLine)
                      .Description("Represents the command line.");

            descriptor.Field(c => c.PlatformId)
                      .Description("Represents the unique ID of the platform which the command belongs.");

            descriptor.Field(c => c.Platform)
                      .ResolveWith<Resolvers>(c => c.GetPlatform(default!, default!))
                      .UseDbContext<AppDbContext>()
                      .Description("This is the platform to which the command belongs.");

        }

        private class Resolvers
        {
            public Platform GetPlatform(Command command, [ScopedService] AppDbContext context)
            {
                return context.Platforms.FirstOrDefault(p => p.Id == command.PlatformId);
            }
        }

public class Startup
    {
        private IConfiguration Configuration { get; }

        public Startup(IConfiguration collection)
        {
            Configuration = collection;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.ConfigureDbContext(Configuration);
            services.ConfigureGraphQL();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseWebSockets();
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGraphQL();
            });

            app.ConfigureGraphQL();
        }

public static class ContexConfiguration
    {
        public static void ConfigureDbContext(this IServiceCollection services, IConfiguration configuration)
        {
            services.AddPooledDbContextFactory<AppDbContext>(options =>
               options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
        }
    }

public static class GraphQLConfiguration
    {
        /// <summary>
        /// Configuration of the GrapQL server
        /// </summary>
        /// <param name="services"></param>
        public static void ConfigureGraphQL(this IServiceCollection services)
        {
            services.AddGraphQLServer()
                    .AddQueryType<Query>()
                    .AddMutationType<Mutation>()
                    .AddSubscriptionType<Subscription>()
                    .AddType<PlatformType>()
                    .AddType<AddPlatformInputType>()
                    .AddType<AddPlatformPayloadType>()
                    .AddType<CommandType>()
                    .AddType<AddCommandInputType>()
                    .AddType<AddCommandPayloadType>()
                    .AddFiltering()
                    .AddSorting()
                    .AddInMemorySubscriptions();
        }

        /// <summary>
        /// GraphQL Voyager UI configuration
        /// </summary>
        /// <param name="app"></param>
        public static void ConfigureGraphQL(this IApplicationBuilder app)
        {
            app.UseGraphQLVoyager(
                options: new VoyagerOptions()
                {
                    GraphQLEndPoint = "/graphql"

                },
                path: "/graphql-voyager"
            );
        }
    }

Upvotes: 1

Views: 2049

Answers (1)

Wasyster
Wasyster

Reputation: 2535

found amswer

offical documentation:

Upvotes: 2

Related Questions