ChilliCream GraphQL中如何在查询参数上使用自定义指令
问题说明
基于.NET Core 6框架搭配ChilliCream v12(Hot Chocolate)开展GraphQL开发时,自定义指令可在类型字段上正常运行,但绑定到查询/变更操作的指定参数上时无法生效。
执行如下查询语句时,仅UserType的Name字段上的指令可正常触发,userByEmail查询的email参数上挂载的指令无响应:
query{ userByEmail(email: "test") { id name email } }
解决方案
Hot Chocolate v12 默认的指令执行管道仅覆盖字段级维度,参数级指令不会自动被字段中间件捕获,需要做两处调整即可让参数指令正常生效:
- 显式指定指令的适用范围
给自定义指令类型配置允许挂载的位置时,除了原本的字段定义位置,必须额外加上DirectiveLocation.ArgumentDefinition,示例配置如下:[DirectiveType( DirectiveLocation.FieldDefinition | DirectiveLocation.ArgumentDefinition // 新增参数定义的挂载位置 )] public class MyCustomDirective : DirectiveType { protected override void Configure(IDirectiveTypeDescriptor descriptor) { descriptor.Name("myCustomDirective"); // 保留原有的指令参数、配置逻辑即可 } } - 注册参数级中间件处理指令逻辑
不要仅依赖字段级UseField中间件处理所有指令逻辑,需要单独实现参数中间件,在服务注册阶段注入管道,用来捕获参数上挂载的指令并执行对应逻辑:- 先实现自定义参数中间件,遍历当前执行字段的所有入参,检测参数上的指令并处理:
public class CustomArgumentDirectiveMiddleware { private readonly FieldDelegate _next; public CustomArgumentDirectiveMiddleware(FieldDelegate next) { _next = next; } public async ValueTask InvokeAsync(IMiddlewareContext context) { // 遍历当前字段的所有入参 foreach (var argument in context.Selection.Field.Arguments) { // 检测当前参数是否挂载了自定义指令 if (argument.Directives.Contains<MyCustomDirective>()) { // 读取参数传入值,执行校验、转换、日志等自定义逻辑 var argumentValue = context.ArgumentValue<object>(argument.Name); // 此处写指令对应的业务逻辑即可 } } await _next(context); } } - 在GraphQL服务注册时,把中间件加入管道:
builder.Services.AddGraphQLServer() // 保留原有的查询类型、类型绑定等注册代码 .AddArgumentMiddleware<CustomArgumentDirectiveMiddleware>();
- 先实现自定义参数中间件,遍历当前执行字段的所有入参,检测参数上的指令并处理:
如果是用注解模式给参数绑定指令,直接在查询/变更方法的对应参数上添加指令特性即可,示例:
public User? GetUserByEmail([MyCustomDirective] string email) { // 原有业务查询逻辑 }
配置完成后重新启动项目,参数上的自定义指令就可以和字段指令一样正常触发执行。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

