async Task <IActionResult> vs Task <T>

Joh*_*anP 7 c# asp.net-mvc asp.net-core

我有一个控制器一个动作.在这个动作方法中,我有一个async我调用的方法,就是这样.这是我正在使用的代码:

[HttpGet]
public Task<MyObject> Get()
{
    return _task.GetMyObject()
}
Run Code Online (Sandbox Code Playgroud)

这正确地序列化为我期望的JSON.现在我的经理坚持要将签名更改为以下内容:

[HttpGet]
public async Task<IActionResult> Get()
{
    var data = await_task.GetMyObject();
    return Ok(data);
}
Run Code Online (Sandbox Code Playgroud)

我相信没有理由将代码await放在控制器中并且可以返回,Task因为事后没有任何东西取决于结果.除了为此完成的额外代码生成(创建状态机等)之外await,从WebApi这些方法的角度来看是否有任何影响?为了澄清,我想知道返回a IActionResult是否比仅返回更好Task<MyObject>似乎结果是相同的.

Aka*_*ava 7

任务<T>

单元测试不需要任何铸造,

 Product product = await controller.Get();
Run Code Online (Sandbox Code Playgroud)

最大的优势是,您的单元测试真正独立于底层 HTTP 堆栈。

Swagger 不需要任何额外的属性来生成响应模式,因为 swagger 可以轻松检测结果类型。

另一个很大的优势是,当逻辑保持不变时,您可以在其他控制器中重用您的控制器。

还避免await在返回之前略微提高性能,因为该部分代码不需要任务状态机。我认为未来的 C# 版本将省略 single await 作为编译器优化。

骗局

返回错误状态代码需要抛出异常..

    throw new HttpStatusException(404, "File not found");
    throw new HttpStatusException(409, "Unauthorized");
Run Code Online (Sandbox Code Playgroud)

任务<IAsyncResult>

您可以返回 HTTP 状态代码,例如

 return NotFound(); // (Status Code = 404)
 return Unauthorized(); // (Status Code = 409)
Run Code Online (Sandbox Code Playgroud)

骗局

单元测试需要额外的铸造..

 Product productResult = ((await controller.Get()) as OkResult).Result as Product;
Run Code Online (Sandbox Code Playgroud)

由于这种强制转换,很难在其他控制器中重用您的控制器,从而导致逻辑重复。

Swagger 生成器需要额外的属性来生成响应模式

 [ProducesResponseType(typeof(Product), 200)]
Run Code Online (Sandbox Code Playgroud)

当你面对的不是单元测试的一部分,而不是你的业务逻辑的一部分,如逻辑只建议使用此方法OAuth使用你想更专注于第三方服务的集成IActionResult成果,例如ChallengeRedirect等等。


Fei*_*hou 5

操作可以返回任何内容,大多数情况下它们返回产生响应的实例IActionResult(或对于异步方法)。Task<IActionResult>操作方法负责选择返回什么样的响应,操作结果负责响应。

如果一个操作返回一个IActionResult实现者,并且控制器继承自 Controller,那么开发人员就有许多与许多选择相对应的辅助方法。返回非IActionResult类型对象的操作的结果将使用适当的IOutputFormatter实现进行序列化。

对于具有多个返回类型或选项的重要操作(例如,基于执行的操作结果的不同 HTTP 状态代码),首选IActionResult作为返回类型。