何时返回IHttpActionResult vs Object

本文关键字:Object vs IHttpActionResult 返回 何时 | 更新日期: 2023-09-27 18:06:03

我看到有两种不同的方法用于向调用jQuery函数返回数据。第一个方法返回类型为Client的对象,但我不确定第二个方法返回什么。

方法# 1

(返回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 vs Object

返回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 .