HotChocolate 是构建 GraphQL 服务的框架,需编写 resolver 方法而非执行 GraphQL 字符串;resolver 要求 public、参数名匹配、支持 IQueryable 优化;返回 null 默认静默,非空字段才报错;UseRouting() 必须在 MapGraphQL() 前;schema 依赖命名约定。
HotChocolate 在 C# 中不是“支持 GraphQL 查询语言”的工具,而是帮你定义、暴露、执行 GraphQL 服务的框架——你写的
或
文本本身不运行在 C# 里,它被 HotChocolate 解析后,才调用你写的 C# resolver 方法。
怎么写一个能被 HotChocolate 执行的 query resolver
你不能直接在 C# 里拼接或执行 GraphQL 字符串(比如
),那只是请求载荷。真正要写的是 resolver —— 一个返回数据的 C# 方法,由 HotChocolate 在收到合法 query 后自动调用。
resolver 必须是 public 实例方法或静态方法,返回可序列化的类型(如
、
、
)
参数名需与 query 中字段参数名一致(如
),HotChocolate 自动绑定;支持
、
等特殊参数
如果返回
,HotChocolate 会自动应用
、
、字段选择(field selection)等优化,但前提是启用了
别在 resolver 里手动解析
字符串——那是 HTTP 层的事,HotChocolate 已帮你做完 AST 解析和变量注入
为什么
resolver 返回 null 却没报错
HotChocolate 默认对 nullable 引用类型字段(如
、
)不做非空校验,即使 resolver 返回
,也会静默渲染为 JSON 中的
,而不是抛出
。
C知道
CSDN推出的一款AI技术问答工具
下载
若字段在 schema 中声明为非空(
),而 resolver 返回
,HotChocolate 才会抛出
错误
启用严格模式:在配置时加
并确保所有类型标注正确(如
vs
)
更可靠的做法是在 resolver 内主动抛异常:
注意:EF Core 的
返回
是正常行为,不等于逻辑错误,是否报错取决于业务语义
和
的顺序不能颠倒
HotChocolate 要求 ASP.NET Core 的端点路由必须先注册,否则
会找不到路由容器,启动时报
或 404。
正确顺序:
→
→
→
是
扩展,必须在
的
阶段调用,且要在
之后、
之前(若用 Minimal Hosting,需用
)
常见坑:把
放在
之后但没加
,结果 GraphQL endpoint 完全不响应
最易被忽略的一点:HotChocolate 的 schema 生成依赖命名约定和泛型推导,比如把 resolver 方法命名为
会自动映射到
字段,但若你写了
又没显式用
,这个字段就不会出现在 schema 里——连 playground 都看不到,更别说查询了。
querymutation"{ user(id: 1) { name } }"UserIQueryableTaskidIResolverContextCancellationTokenIQueryable@skip@includeAddGraphQLServer().AddProjections()context.Request.QueryGetUserByIdstringUsernullnullExecutionErrorUser!null"Cannot return null for non-nullable field".ModifyOptions(o => o.RemoveUnreachableTypes = true)User?Userif (user == null) throw new ExecutionError($"User {id} not found");FirstOrDefaultAsync()nullUseRouting()AddGraphQLServer()MapGraphQL()"No endpoint was configured for GraphQL"app.UseRouting();app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints => endpoints.MapGraphQL());AddGraphQLServer()IServiceCollectionProgram.csbuilder.ServicesAddControllers()AddEndpointsApiExplorer()builder.AddGraphQLServer()MapGraphQL()UseStaticFiles()UseRouting()GetUsersusersFetchAllUsers[GraphQLName("users")]