我有一个控制器,只有一个动作。在这个动作方法中,我调用了一个async
方法,就是这样。这是我正在使用的代码:
[HttpGet]
public Task<MyObject> Get()
{
return _task.GetMyObject()
}
这正确地序列化为我期望的JSON。现在我的经理坚持要将签名更改为以下内容:
[HttpGet]
public async Task<IActionResult> Get()
{
var data = await_task.GetMyObject();
return Ok(data);
}
我相信控制器中的await
代码没有理由可以返回Task
,因为之后没有任何内容取决于结果。除了为await
完成的额外代码生成(创建状态机等)之外,从WebApi
这些方法的角度来看是否有任何影响?为了澄清,我想知道返回IActionResult
是否比返回Task<MyObject>
更好,即使结果看起来是相同的。
答案 0 :(得分:3)
<强>任务&LT; T&GT; 强>
<强>临强>
单元测试不需要任何演员,
Product product = await controller.Get();
最大的优点是,您的单元测试真正独立于底层HTTP Stack。
Swagger不需要任何额外的属性来生成响应模式,因为swagger可以轻松检测结果类型。
另一个很大的优点是,当逻辑保持不变时,您可以在其他控制器中重用控制器。
在返回之前避免await
会略微提高性能,因为该部分代码不需要任务状态机。我认为未来的C#版本将省略单个等待编译器优化。
<强> N 强>
返回错误状态代码需要抛出异常..
throw new HttpStatusException(404, "File not found");
throw new HttpStatusException(409, "Unauthorized");
<强>任务&LT; IAsyncResult的&GT; 强>
<强>临强>
您可以返回HTTP状态代码,例如
return NotFound(); // (Status Code = 404)
return Unauthorized(); // (Status Code = 409)
<强> N 强>
单元测试需要额外的铸造......
Product productResult = ((await controller.Get()) as OkResult).Result as Product;
由于这样的转换,很难在其他控制器中重用控制器,导致逻辑重复。
Swagger生成器需要额外的属性来生成响应模式
[ProducesResponseType(typeof(Product), 200)]
这种方法仅在您处理不属于单元测试的逻辑时推荐,而不是您的业务逻辑的一部分,例如OAuth
与第三方服务的集成,您希望更多地关注IActionResult
基于1}}的结果,例如Challenge
,Redirect
等。
答案 1 :(得分:1)
操作可以返回任何内容,但经常返回生成响应的IActionResult
(或Task<IActionResult>
用于异步方法)的实例。动作方法负责选择何种响应。操作结果会响应。
如果某个操作返回IActionResult
实现并且控制器继承自Controller,那么开发人员可以使用许多辅助方法来对应许多选项。返回非IActionResult
类型对象的操作的结果将使用相应的IOutputFormatter
实现进行序列化。
对于具有多种返回类型或选项的非平凡操作(例如,基于执行的操作结果的不同HTTP状态代码),首选IActionResult
作为返回类型。
答案 2 :(得分:1)
ASP.NET MVC是一个conventions over configuration框架。这意味着您的代码的任何未来维护者,包括您未来的自己,都希望代码能够以某种方式编写,以减少您必须检查以进行更改或添加的类文件的数量。
虽然结果可能与您的两个技术上不同的选项相同,但传统方法是异步/等待您的结果。除了该约定之外的任何其他内容都可能会对未来的维护者造成混淆。此外,未来版本的MVC可能会以未知的方式破坏您的代码,因为您没有遵循惯例。
软件开发团队的良好领导包括通过简化代码的潜在未来维护来灌输降低组织总体人力需求的愿望。您的经理可能正试图推广这一概念。
答案 3 :(得分:0)
ASP.NET核心团队在统一MVC和WEB API(Controller和ApiController)的同时,抽象出了IActionResult,以实现强大的异常处理机制。
控制流的异常抛出是对行动方法的反模式。
[HttpGet]
public async Task<MyObject> Get()
{
var data = await _task.GetMyObject()
if(data == null)
{
return NotFound(); //Or, return Request.CreateResponse(HttpStatusCode.NotFound)
// Versus, throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
return Ok(data);
}
注意: NotFound()
,Ok()
等是WEBAPI2时代的IHttpActionResult
内容,而不是asp.net核心新手。