在Core 2.2中返回异步结果时无法使用Ok(...)作为状态代码

时间:2019-08-01 12:22:19

标签: c# asynchronous asp.net-core asp.net-web-api asp.net-core-2.2

我像这样搭建了一个WebAPI模板。

[HttpGet]
public async Task<ActionResult<IEnumerable<ThingVm>>> GetThings()
{
  Task<List<ThingVm>> output = Context.Things
    .Select(e => new ThingVm(e))
    .ToListAsync();
  return await output;
}

我注意到返回的结果将不会传递任何状态代码(因为我未提供200或404等)。因此,我添加了常规的标准Ok(...)调用。

[HttpGet]
public async Task<ActionResult<IEnumerable<ThingVm>>> GetThings()
{
  ...
  return await Ok(output);
}

遗憾的是,计算机没有意识到该操作,并解释了这种错误。

  

CS1061'OkObjectResult'不包含'GetAwaiter'的定义,并且无法找到接受类型为'OkObjectResult'的第一个参数的可访问扩展方法'GetAwaiter'(您是否缺少using指令或程序集引用?)< / p>

我明白为什么会这样。我不知道如何解决该问题,同时保留与响应一起发出的状态代码。

我用Google搜索了它,但在insanely old stufftotally irrelevant stuffrather unrelated stuff上获得了成功。就是这样-几乎没有其他热门歌曲,这也令人惊讶。

如何发出状态代码并应用异步方法?它们不是互斥的,对吗?

2 个答案:

答案 0 :(得分:4)

您为什么不等待结果呢?

[HttpGet]
public async Task<ActionResult<IEnumerable<ThingVm>>> GetThings()
{
  var output = await Context.Things
    .Select(e => new ThingVm(e))
    .ToListAsync();

  return Ok(output);
}

答案 1 :(得分:4)

从评论看来,实际问题是如何将结果流式传输到客户端。这在ASP.NET Core 2.2中是不可能的。异步操作(ToListAsync())必须先完成:

[HttpGet]
public async Task<ActionResult<IEnumerable<ThingVm>>> GetThings()
{
  Task<List<ThingVm>> output = Context.Things
    .Select(e => new ThingVm(e))
    .ToListAsync();
  return await output;
}

随着IAsyncEnumerable<T>的引入,这在.NET Core 3中发生了变化。文章What's the big deal with IAsyncEnumerable in .NET Core 3.0?展示了异步操作如何一次返回所有结果

public async Task<IEnumerable<Product>> GetAllProducts()

可以转换为:

[HttpGet]
public IAsyncEnumerable<Product> Get()
    => productsRepository.GetAllProducts();

ASP.NET Core知道IAsyncEnumerable<T>,并将在每个结果对象到达时将它们写入输出流。

EF Core 3还支持IAsyncEnumerable,这意味着GetThings()可以更改为:

[HttpGet]
public IAsyncEnumerable<ThingVm> GetThings()
{
    var query = Context.Things
        .Select(e => new ThingVm(e))
        .AsAsyncEnumerable();
  return query;
}

AsAsyncEnumerable没什么特别的,它只是将查询强制转换为IAsyncEnumerable

一个很好的好处是我们的代码不再需要分配一个大列表或数组来保存结果,然后再返回它们

上线

.NET Core 3.0预览版7具有Go Live license and can be used in production