You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET5 Web API集成GraphQL返回非预期数据问题求助

问题原因

你遇到的返回全量字段、包含未定义属性的问题是两个核心错误导致的:

  1. 控制器直接将ExecutionResult.Data交给ASP.NET Core默认JSON序列化器输出。默认序列化器会无视GraphQL的字段筛选规则,直接序列化返回实体的所有公共属性(包括你没在TodoItemType里定义的DomainEvents等字段)。
  2. 未按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 06:45:03