.NET5 Web API集成GraphQL返回非预期数据问题求助
问题原因
你遇到的返回全量字段、包含未定义属性的问题是两个核心错误导致的:
- 控制器直接将
ExecutionResult.Data交给ASP.NET Core默认JSON序列化器输出。默认序列化器会无视GraphQL的字段筛选规则,直接序列化返回实体的所有公共属性(包括你没在TodoItemType里定义的DomainEvents等字段)。 - 未按GraphQL规范序列化完整执行结果,错误的直接返回
Data节点,同时请求错误时直接返回BadRequest,不符合GraphQL接口的返回规范。
修复步骤
1. 调整控制器注入与返回逻辑
首先在控制器中注入GraphQL专用的IDocumentWriter,替换原有返回逻辑,用专用序列化器输出结果:
[Route("graphql")] public class GraphQlController : Controller { private readonly ISchema _schema; private readonly IDocumentExecuter _executer; // 新增注入IDocumentWriter private readonly IDocumentWriter _documentWriter; public GraphQlController(ISchema schema, IDocumentExecuter executer, IDocumentWriter documentWriter) { _schema = schema; _executer = executer; _documentWriter = documentWriter; } [HttpPost] public async Task<IActionResult> Post([FromBody] GraphQLQueryDTO query) { var result = await _executer.ExecuteAsync(_ => { _.Schema = _schema; _.Query = query.Query; _.Inputs = query.Variables?.ToInputs(); // 绑定取消令牌 _.CancellationToken = HttpContext.RequestAborted; }); // 按GraphQL规范,即使有错误也返回完整结构,不要直接返回BadRequest if (result.Errors?.Count > 0) { Response.StatusCode = StatusCodes.Status400BadRequest; } Response.ContentType = "application/json"; // 用GraphQL专用序列化器输出结果,会自动按请求字段裁剪 await _documentWriter.WriteAsync(Response.Body, result); return new EmptyResult(); } }
2. 服务注册补充配置
确保你在Startup.cs/Program.cs中注册GraphQL服务时,已经添加了序列化相关配置,.NET 5对应的配置示例如下:
services.AddGraphQL() .AddSystemTextJson() // 配置GraphQL专用序列化器 .AddSchema<TodoItemSchema>() // 替换为你实际的Schema类 .AddGraphTypes(typeof(TodoItemQuery).Assembly); // 自动扫描注册所有GraphType
3. 可选优化(建议修改)
将查询定义中的同步ToList改为异步调用,避免线程阻塞:
public TodoItemQuery(IApplicationDbContext context) { Field<ListGraphType<TodoItemType>>("items", "", null, // 改为异步Resolve resolve: async c => await context.TodoItems.ToListAsync(c.CancellationToken)); Field<TodoItemType>("item","", new QueryArguments( new QueryArgument<IntGraphType>{Name = "id"}), resolve: async c => { var id = c.GetArgument<int>("id"); return await context.TodoItems.FirstOrDefaultAsync(item => item.Id == id, c.CancellationToken); }); }
修改完成后即可正常返回仅请求的字段,不会出现多余属性。
内容的提问来源于stack exchange,提问作者Michael Snytko
相关产品推荐
相关产品推荐

