【问题标题】:How to return ActionResult along with async foreach and IAsyncEnumerable如何与异步 foreach 和 IAsyncEnumerable 一起返回 ActionResult
【发布时间】:2020-06-21 06:55:16
【问题描述】:

我有这个签名的控制器方法:

public async IAsyncEnumerable<MyDto> Get()

它工作正常,但我需要做一些请求验证并相应地返回 401、400 和其他代码,它不支持。 或者,以下签名无法编译:

public async Task<ActionResult<IAsyncEnumerable<MyDto>>> Get()

错误:

不能隐式转换类型 'Microsoft.AspNetCore.Mvc.UnauthorizedResult' 到 'MyApi.Responses.MyDto'

完整方法:

public async IAsyncEnumerable<MyDto> Get()
{
    if (IsRequestInvalid())
    {
        // Can't do the following. Does not compile.
        yield return Unauthorized();
    }
    var retrievedDtos = _someService.GetAllDtosAsync(_userId);

    await foreach (var currentDto in retrievedDtos)
    {
        yield return currentDto;
    }
}

有什么想法吗?似乎无法相信 Microsoft 已将 IAsyncEnumerable 设计为在没有返回其他任何内容的可能性/灵活性的情况下使用。

【问题讨论】:

  • 这与IAsyncEnumerable 关系不大。如果您使用async Task&lt;MyDTO&gt;,您也会遇到同样的问题。如果您想返回特定响应,请返回IActionResultActionResult&lt;T&gt;
  • 这是解释in the docsIn such a case, it's common to mix an ActionResult return type with the primitive or complex return type. Either IActionResult or ActionResult&lt;T&gt; are necessary to accommodate this type of action.
  • @PanagiotisKanavos 这不是同一个问题,因为在 Task 的情况下,我可以很容易地做到Task&lt;ActionResult&lt;MyDto&gt;&gt;,而我不能做到Task&lt;ActionResult&lt;IAsyncEnumerable&lt;MyDto&gt;&gt;&gt;(如问题中所述)。我需要 IAsyncEnumerable 在结果到达时将结果传递给序列化程序。
  • 这是完全同样的问题 - 除非您返回 ActionResultIActionResult,否则您无法返回状态。问题是如何返回它,保持 IAsyncEnumerable 的好处。查看实际发送对象结果的类the source for ObjectResultExecutor,我看到它有代码到handle IAsyncEnumerable
  • 您可以尝试返回ActionResult&lt;IAsyncEnumerable&gt;,例如:return Ok(retrievedDtos)

标签: c# asp.net-core-webapi actionresult request-validation iasyncenumerable


【解决方案1】:

这应该可以工作

    public ActionResult<IAsyncEnumerable<MyDto>> Get()
    {
        if(IsRequestInvalid())
        {
            // now can do.
            return Unauthorized();
        }

        return new ActionResult<IAsyncEnumerable<MyDto>>(DoSomeProcessing());

        IAsyncEnumerable<MyDto> DoSomeProcessing()
        {
            IAsyncEnumerable<MyDto> retrievedDtos = _someService.GetAllDtosAsync(_userId);

            await foreach(var currentDto in retrievedDtos)
            {
                //work with currentDto here

                yield return currentDto;
            }
        }
    }

如果在退货之前没有处理过物品更好:

public ActionResult<IAsyncEnumerable<MyDto>> Get()
    {
        if(IsRequestInvalid())
        {
            // now can do
            return Unauthorized();
        }

        return new ActionResult<IAsyncEnumerable<MyDto>>(_someService.GetAllDtosAsync(_userId));
    }

【讨论】:

    猜你喜欢
    • 2020-04-28
    • 2013-09-11
    • 2021-12-29
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    相关资源
    最近更新 更多