【问题标题】:Why should I use IHttpActionResult instead of HttpResponseMessage?为什么我应该使用 IHttpActionResult 而不是 HttpResponseMessage?
【发布时间】:2014-03-12 14:09:04
【问题描述】:

我一直在使用 WebApi 进行开发,并转向 WebApi2,其中 Microsoft 引入了一个新的 IHttpActionResult 接口,似乎建议使用它而不是返回 HttpResponseMessage。我对这个新界面的优势感到困惑。它似乎主要只是提供了一种稍微更简单的方法来创建HttpResponseMessage

我认为这是“为抽象而抽象”。我错过了什么吗?除了可以节省一行代码之外,我使用这个新界面还能获得哪些现实世界的优势?

旧方式(WebApi):

public HttpResponseMessage Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    else
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

新方式(WebApi2):

public IHttpActionResult Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        //return new HttpResponseMessage(HttpStatusCode.OK);
        return Ok();
    }
    else
    {
        //throw new HttpResponseException(HttpStatusCode.NotFound);
        return NotFound();
    }
}

【问题讨论】:

  • 我刚刚发现了一些有趣的东西。我不确定这些结果是否可以被其他人验证。但是通过我做的一些调用,性能得到了很大改善: * 以使用HttpResponseMessage 的示例为例,我在 9545 毫秒 内得到了响应。 * 使用 IHttpActionResult 我在 294 毫秒 内得到了相同的响应。
  • @chrislesage 9545 毫秒几乎是 10 秒。即使是 294 毫秒也有点慢。如果你有任何超过 100 毫秒的东西,那么还有其他东西在起作用。这个故事不仅仅是遇到了 ete。

标签: c# asp.net-web-api httpresponse


【解决方案1】:

您可能决定不使用IHttpActionResult,因为您现有的代码构建了一个不适合其中一个预设响应的HttpResponseMessage。但是,您可以使用 ResponseMessage 的预设响应将 HttpResponseMessage 调整为 IHttpActionResult。我花了一段时间才弄清楚这一点,所以我想发布它以表明您不必选择其中一个:

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //we want a 303 with the ability to set location
   HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
   responseMsg.Headers.Location = new Uri("http://customLocation.blah");
   response = ResponseMessage(responseMsg);
   return response;
}

注意,ResponseMessage 是您的控制器应继承自基类 ApiController 的方法。

【讨论】:

  • 我花了一段时间才发现 ResponseMessage 现在是 ResponseMessageResult。也许它最近改名了?附言您还错过了答案中的新关键字,非常感谢您的建议:)
  • @IlyaChernomordik ResponseMessageResponseMessageResult 是两个不同的东西。 ResponseMessage()ApiController方法,你的控制器应该从它继承,因此只是一个方法调用。所以那里不需要new 关键字。您可能没有从 ApiController 继承,或者您在静态方法中。 ResponseMessageResultResponseMessage() 的返回类型。
  • @IlyaChernomordik 我本可以写response = base.ResponseMessage(responseMsg) 以更清楚地表明它是基类 ApiController 的方法
  • 谢谢,我确实有一个服务不是从 ApiController 继承的,所以花了一些时间才找到。
  • @AaronLS 是正确的。应该是return new ResponseMessageResult(new HttpResponseMessage(HttpStatusCode.RedirectMethod));
【解决方案2】:

您仍然可以使用HttpResponseMessage。这种能力不会消失。我和你有同样的感觉,并与团队广泛争论不需要额外的抽象。有一些争论试图证明它的存在,但没有一个能让我相信它是值得的。

也就是说,直到我看到 Brad Wilsonthis 样本。如果您以可链接的方式构建IHttpActionResult 类,您将能够创建一个“action-level” 响应管道以生成HttpResponseMessage。在幕后,这就是 ActionFilters 的实现方式,但是,在阅读动作方法时,这些 ActionFilters 的顺序并不明显,这是我不喜欢动作过滤器的原因之一。

但是,通过创建可以显式​​链接到您的操作方法中的IHttpActionResult,您可以组合各种不同的行为来生成您的响应。

【讨论】:

    【解决方案3】:

    下面是IHttpActionResult 相对于Microsoft ASP.Net Documentation 中提到的HttpResponseMessage 的几个好处:

    • 简化对控制器的单元测试。
    • 将用于创建 HTTP 响应的通用逻辑移到单独的类中。
    • 通过隐藏构造响应的低级细节,使控制器操作的意图更加清晰。

    但这里还有一些值得一提的使用IHttpActionResult的优势:

    • 尊重单一职责原则:让 action 方法负责为 HTTP 请求提供服务,而不涉及它们创建 HTTP 响应消息。
    • 有用的实现已在 System.Web.Http.Results 中定义,即:OkNotFoundExceptionUnauthorizedBadRequestConflictRedirectInvalidModelState(link to full list )
    • 默认使用 Async 和 Await
    • 只需实现ExecuteAsync 方法即可轻松创建自己的ActionResult
    • 您可以使用ResponseMessageResult ResponseMessage(HttpResponseMessage response)将 HttpResponseMessage 转换为 IHttpActionResult

    【讨论】:

      【解决方案4】:
      // this will return HttpResponseMessage as IHttpActionResult
      return ResponseMessage(httpResponseMessage); 
      

      【讨论】:

        【解决方案5】:

        这只是我的个人观点,Web API 团队的人可能会更好地表达它,但这是我的 2c。

        首先,我认为这不是一个人对另一个人的问题。您可以根据要在操作方法中执行的操作同时使用它们,但为了了解IHttpActionResult 的真正威力,您可能需要跳出ApiController 的那些方便的辅助方法,例如OkNotFound

        基本上,我认为将IHttpActionResult 实现为HttpResponseMessage 的工厂的类。有了这种心态,它现在变成了一个需要返回的对象和一个生产它的工厂。在一般编程意义上,您可以在某些情况下自己创建对象,在某些情况下,您需要一个工厂来执行此操作。这里也一样。

        如果你想返回一个需要通过复杂逻辑构建的响应,比如很多响应头等,你可以将所有这些逻辑抽象到一个实现IHttpActionResult的动作结果类中,并在多个动作方法中使用它返回响应。

        使用IHttpActionResult 作为返回类型的另一个优点是它使 ASP.NET Web API 操作方法类似于 MVC。您可以返回任何操作结果,而不会陷入媒体格式化程序。

        当然,正如 Darrel 所指出的,您可以链接操作结果并创建一个强大的微管道,类似于 API 管道中的消息处理程序本身。这取决于您的操作方法的复杂性。

        长话短说 - 不是 IHttpActionResultHttpResponseMessage。基本上,这就是您想要创建响应的方式。自己做或通过工厂做。

        【讨论】:

        • 工厂理由的问题是我可以轻松地创建像ResponseFactory.CreateOkResponse() 这样返回HttpResponseMessage 的静态方法,并且在创建响应时我不必处理异步的东西。一位团队成员确实提到了这样一个事实,即如果您需要执行 I/O 以生成标头值,异步会很有用。但不确定这种情况发生的频率。
        • 我认为这和为什么我们需要工厂方法模式是一样的。为什么不只使用静态方法来创建对象。当然,这是可行的——每个对象的创建都不值得采用适当的工厂模式。但是恕我直言,这取决于您要如何建模您的课程。您是否希望有逻辑来创建不同类型的响应,所有这些响应都以多个静态方法的形式塞入一个类中,或者具有基于接口的不同类。同样,没有好坏之分。这一切都取决于。无论如何,我的观点是它不是一个又一个,我个人更喜欢工厂的东西:)
        【解决方案6】:

        Web API 基本上返回 4 种类型的对象:voidHttpResponseMessageIHttpActionResult 和其他强类型。 Web API 的第一个版本返回 HttpResponseMessage,这是非常直接的 HTTP 响应消息。

        IHttpActionResult 是由 WebAPI 2 引入的,它是HttpResponseMessage 的一种包装。它包含创建HttpResponseMessageExecuteAsync() 方法。它简化了控制器的单元测试。

        其他返回类型是一种强类型类,由 Web API 使用媒体格式化程序序列化到响应正文中。缺点是您不能直接返回错误代码,例如 404。您所能做的就是抛出 HttpResponseException 错误。

        【讨论】:

          【解决方案7】:

          我宁愿为IHttpActionResult实现TaskExecuteAsync接口函数。比如:

              public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
              {
                  var response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
          
                  switch ((Int32)_respContent.Code)
                  { 
                      case 1:
                      case 6:
                      case 7:
                          response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
                          break;
                      case 2:
                      case 3:
                      case 4:
                          response = _request.CreateResponse(HttpStatusCode.BadRequest, _respContent);
                          break;
                  } 
          
                  return Task.FromResult(response);
              }
          

          ,其中 _request 是 HttpRequest,_respContent 是有效负载。

          【讨论】:

            【解决方案8】:

            相对于HttpResponseMessage,使用IHttpActionResult 有以下好处:

            1. 通过使用IHttpActionResult,我们只关注要发送的数据而不是状态代码。所以这里的代码会更干净,也很容易维护。
            2. 已实现控制器方法的单元测试将更容易。
            3. 默认使用asyncawait

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-05-23
              • 2018-05-10
              • 2012-12-13
              • 2013-11-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多