ASP.NET Core 7中HotChocolate添加GraphQL对象类型报错求助
在ASP.NET Core 7中使用HotChocolate开发GraphQL API的问题排查与解决
问题场景
在ASP.NET Core 7项目中使用HotChocolate库开发GraphQL API时,添加PlatformType类后,API请求无法正常处理。
相关代码
Query类
using CommanderGQL.Data; using CommanderGQL.Models; namespace CommanderGQL.GraphQL { public class Query { [UseDbContext(typeof(AppDbContext))] [UseProjection] public IQueryable<Platform> GetPlatform([ScopedService] AppDbContext context) { return context.Platforms; } [UseDbContext(typeof(AppDbContext))] [UseProjection] public IQueryable<Command> GetCommand([ScopedService] AppDbContext context) { return context.Commands; } } }
Platform实体类
using System.ComponentModel.DataAnnotations; namespace CommanderGQL.Models { public class Platform { [Key] public int Id { get; set; } [Required] public string Name { get; set; } = string.Empty; public string LicenseKey { get; set; } = string.Empty; public ICollection<Command> Commands { get; set; } = new List<Command>(); } }
Command实体类
using System.ComponentModel.DataAnnotations; namespace CommanderGQL.Models { public class Command { [Key] public int Id { get; set; } [Required] public string HowTo { get; set; } [Required] public string CommandLine { get; set; } [Required] public int PlatformId { get; set; } public Platform Platform { get; set; } } }
PlatformType类(疑似问题代码)
using CommanderGQL.Data; using CommanderGQL.Models; namespace CommanderGQL.GraphQL.Platforms { public class PlatformType : ObjectType<Platform> { protected override void Configure(IObjectTypeDescriptor<Platform> descriptor) { descriptor.Description("Represents any software that has a command line interface"); descriptor .Field(p => p.LicenseKey).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); } } } }
Program.cs配置
builder.Services .AddGraphQLServer() .AddQueryType<Query>() .AddType<PlatformType>() .AddType<CommandType>() .AddFiltering() .AddSorting() .AddProjections();
测试请求与错误响应
执行GraphQL请求:
query { platform { id name commands { howTo commandLine platformId } } }
得到错误响应:
{ "errors": [ { "message": "There was no argument with the name `platform` found on the field `commands`.", "locations": [ { "line": 6, "column": 5 } ], "path": [ "platform", 2, "commands" ], "extensions": { "fieldName": "commands", "argumentName": "platform" } }, { "message": "There was no argument with the name `platform` found on the field `commands`.", "locations": [ { "line": 6, "column": 5 } ], "path": [ "platform", 1, "commands" ], "extensions": { "fieldName": "commands", "argumentName": "platform" } }, { "message": "There was no argument with the name `platform` found on the field `commands`.", "locations": [ { "line": 6, "column": 5 } ], "path": [ "platform", 0, "commands" ], "extensions": { "fieldName": "commands", "argumentName": "platform" } } ] }
问题原因
错误核心是:在PlatformType中配置Commands字段时,使用ResolveWith指定解析方法时,HotChocolate错误地将方法的第一个参数Platform platform识别为GraphQL字段的输入参数。但实际上这个参数是当前字段的父对象实例(即当前查询到的Platform对象),不需要作为请求参数传入,因此查询时找不到对应的platform参数而报错。
解决方案
方案一:用[Parent]标记父对象参数
修改Resolvers类的GetCommands方法,给platform参数加上[Parent]特性,明确告知HotChocolate这是父对象,不是输入参数:
private class Resolvers { public IQueryable<Command> GetCommands([Parent] Platform platform, [ScopedService] AppDbContext context) { return context.Commands.Where(p => p.PlatformId == platform.Id); } }
方案二:改用Resolve方法直接编写逻辑
替换ResolveWith为Resolve,直接在配置逻辑中获取父对象和服务,避免参数解析问题:
descriptor .Field(p => p.Commands) .Resolve(ctx => { // 获取父对象(当前Platform实例) var platform = ctx.Parent<Platform>(); // 获取DbContext服务 var dbContext = ctx.Service<AppDbContext>(); return dbContext.Commands.Where(p => p.PlatformId == platform.Id); }) .UseDbContext<AppDbContext>() .Description("This is the list of available commands for this platform");
可选优化:利用EF Core导航属性自动加载
如果你的EF Core已经正确配置了Platform和Command的关联关系(如在DbContext中设置了导航属性),其实可以不需要手动编写Resolver。HotChocolate会自动通过EF Core的导航属性加载关联数据,只需确保Query类中使用了UseProjection特性,这样代码会更简洁。
正确添加GraphQL类型的要点
- 自定义ObjectType时,确保字段配置的参数类型被正确识别:父对象用
[Parent]标记,服务用[ScopedService]等标记,避免被误识别为输入参数。 - 对于实体间的关联字段,优先利用EF Core导航属性,减少手动Resolver的编写。
- 在Program.cs中通过
AddType<T>()注册自定义类型,确保GraphQL Server能识别这些类型。
内容的提问来源于stack exchange,提问作者Protsyk Yaroslav
相关产品推荐
相关产品推荐

