何时返回IHttpActionResult vs Object
本文关键字:Object vs IHttpActionResult 返回 何时 | 更新日期: 2023-09-27 18:06:03
我看到有两种不同的方法用于向调用jQuery函数返回数据。第一个方法返回类型为Client
的对象,但我不确定第二个方法返回什么。
(返回
Client
对象)public IEnumerable<Client> GetAllClients()
{
using (var context = new PQRSModel.PQRSEntities())
{
context.Configuration.ProxyCreationEnabled = false;
var query = context.Clients.OrderBy(c = c.OrgName);
var customers = query.ToList();
return customers;
}
}
方法#2 (IHttpActionResult
提供什么好处?)
public IHttpActionResult GetClient(int clientId)
{
using (var context = new PQRSModel.PQRSEntities())
{
context.Configuration.ProxyCreationEnabled = false;
var client = context.Clients.FirstOrDefault(c = c.ID == clientId);
if (client == null)
{
return NotFound();
}
return Ok(client);
}
}
如果第二个方法找到一个对象,是否有任何理由它不能也返回一个Client
对象类型?
返回IHttpActionResult
提供了一个很好的关注点分离。
控制器可以专注于以最合理的方式响应请求(状态码、错误消息等)。另一个(服务)层可以专注于实际检索和转换业务数据。
副作用是,你的控制器方法变得更加单元可测试。考虑下面的简单示例:public class MyController : ApiController
{
//or better yet, dependency-inject this
SomeService _service = new SomeService();
public IHttpActionResult Get(int id)
{
if (id < 0)
return BadRequest("Some error message");
var data = _service.GetData(id);
if (data == null)
return NotFound();
return Ok(data);
}
}
这个方法的逻辑不仅可以通过读取来理解,而且您现在可以更容易和自然地测试逻辑,例如(使用NUnit语法):
[TestFixture]
public class MyControllerTests
{
[Test]
public void Get_WithIdLessThan0_ReturnsBadRequest()
{
var controller = new MyController();
int id = -1;
IHttpActionResult actionResult = controller.Get(id);
Assert.IsInstanceOf<BadRequestErrorMessageResult>(actionResult);
}
}
类似地,您可以模拟服务层并测试当您将已知的id
参数提供给控制器等时会发生什么。
这是一篇关于Web Api中单元测试控制器的好文章
第二个方法允许您只返回状态码(如示例中的404)、流文件内容和其他类型的非对象内容。
使用IHttpActionResult
的理由是它允许您从Action返回不同的状态码。
让我们考虑下面的例子:
public Client GetClient(int id)
{
if (id <= 0)
{
throw new BadRequestException("Invalid Id"); // 400
}
var client = _myDbService.GetClient(id);
if (client == null)
{
throw new NotFoundException("Client not found"); // 404
}
return Ok(client); // 200
}
返回400和404的唯一方法是抛出异常。
注意上面的代码不包括异常处理逻辑。您需要编写逻辑,以便在异常处理程序中返回所需的状态码和任何额外的错误消息(如果有的话)。
如果我们将返回类型更改为IHttpActionResult
,那么我们可以处理失败场景而不会抛出任何异常:
[SwaggerResponse(HttpStatusCode.OK, "Client found", Type = typeof(Client))]
[SwaggerResponse(HttpStatusCode.BadRequest, "Invalid id")]
[SwaggerResponse(HttpStatusCode.NotFound, "Client not found")]
public IHttpActionResult GetClient(int id)
{
if (id <= 0)
{
return BadRequest("Invalid id");
}
var client = _myDbService.GetClient(id);
if (client == null)
{
return NotFound();
}
return Ok(client);
}
注意,您可以使用SwaggerResponse
属性来指定每个状态码的返回类型。
我不知道哪种方法更好,但微软似乎更喜欢第二种方法:
这种方法的一个缺点是你不能直接返回错误码,如404。然而,你可以扔一个HttpResponseException for error code .