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

.NET Minimal API异步POST查询MongoDB返回空响应问题求助

问题描述

搭建了一个Minimal API,其中POST接口/query接收原始JSON格式的查询条件以操作MongoDB,相关代码如下:

app.MapPost("/query", async (HttpContext context) => await FreeQuery(context));

FreeQuery是异步方法,返回IEnumerable<PreOrder>,但该异步版本会引发内部服务器错误,客户端收到空响应(Content-Length为0),具体实现代码:

async Task<IEnumerable<PreOrder>> FreeQuery(HttpContext context)
{
    using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8))
    {
        string query = await reader.ReadToEndAsync();

        var filter = BsonDocument.Parse(query);

        var result = _collection.Find(filter);

        var list = EnumFromBson<PreOrder>(result);

        Console.WriteLine(list.Count());

        return list;
    }
}

控制台打印list.Count()结果为34,但客户端获取不到有效数据。另外同步版本的GET请求可以正常工作,代码如下:

IEnumerable<PreOrder> FindByField(string field, string value)
{
    var filter = Builders<BsonDocument>.Filter.Eq(field, value);
    var result = _collection.Find(filter);

    var list = EnumFromBson<PreOrder>(result);

    return list;
}
解决方案
  • 核心问题:MongoDB的Find()返回的IFindFluent是延迟执行的查询对象,同步版本中调用Count()会触发立即枚举,但异步方法返回IEnumerable<PreOrder>后,ASP.NET Core框架在序列化时再去枚举时,可能因上下文资源已释放或异步状态问题导致无法获取数据。同时,异步方法中未正确使用MongoDB的异步查询API,导致查询未完成就返回了延迟枚举对象。
  • 修复步骤:
    1. 异步获取MongoDB查询结果:将_collection.Find(filter)改为异步获取列表,使用await result.ToListAsync(),确保数据在返回前已全部加载到内存:
      var result = await _collection.Find(filter).ToListAsync();
      
    2. 调整EnumFromBson方法:修改该方法接收List<BsonDocument>(或已枚举的集合),而非IFindFluent,确保处理的是已加载的数据:
      // 假设原EnumFromBson是处理IFindFluent,现在改为处理List<BsonDocument>
      List<PreOrder> EnumFromBson<T>(List<BsonDocument> documents)
      {
          // 自定义转换逻辑
      }
      
    3. 返回具体集合类型而非IEnumerable:将方法返回类型改为Task<List<PreOrder>>,返回已加载的列表,避免延迟执行带来的序列化问题:
      async Task<List<PreOrder>> FreeQuery(HttpContext context)
      {
          using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8))
          {
              string query = await reader.ReadToEndAsync();
      
              var filter = BsonDocument.Parse(query);
      
              var result = await _collection.Find(filter).ToListAsync();
      
              var list = EnumFromBson<PreOrder>(result);
      
              Console.WriteLine(list.Count);
      
              return list;
          }
      }
      
    4. 简化请求体读取:在Minimal API中可以直接绑定JSON到BsonDocument,无需手动读取Stream,代码更简洁且不易出错:
      app.MapPost("/query", async (BsonDocument filter, IMongoCollection<BsonDocument> collection) =>
      {
          var result = await collection.Find(filter).ToListAsync();
          var list = EnumFromBson<PreOrder>(result);
          return list;
      });
      
  • 验证逻辑:修改后,返回的List<PreOrder>是已完全加载的集合,ASP.NET Core框架可以正常序列化为JSON响应,客户端能正确接收数据。

内容的提问来源于stack exchange,提问作者Serve Laurijssen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:55:17