为什么我应该使用IHttpActionResult而不是HttpResponseMessage?

我一直在使用WebApi进行开发,并转向WebApi2,微软已经推出了一个新的IHttpActionResult接口,似乎build议用于返回一个HttpResponseMessage 。 我很困惑这个新界面的优点。 它似乎主要只是提供一个更轻松的方式来创build一个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(); } } 

您可能决定不使用IHttpActionResult因为您现有的代码构build了不适合其中一个jar头响应的HttpResponseMessage 。 但是,您可以使用ResponseMessage IHttpActionResult响应将HttpResponseMessage调整为IHttpActionResult 。 我花了一段时间才弄明白这一点,所以我想发布一下,表明你不必select一个或另一个:

 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是您的控制器应inheritance的基类ApiController一种方法。

你仍然可以使用HttpResponseMessage 。 这种能力不会消失。 我感觉和你一样,并广泛地与团队争辩说,不需要额外的抽象。 有几个论据试图certificate它的存在,但没有任何说服我认为这是值得的。

也就是说,直到我看到Brad Wilson的 这个样本。 如果以可链接的方式构造IHttpActionResult类,则可以创build“动作级别”响应pipe道来生成HttpResponseMessage 。 下面是ActionFilters的实现方式,但是在阅读action方法时这些ActionFilters的顺序并不明显,这也是我不是动作filter粉丝的原因之一。

但是,通过创buildIHttpActionResults可以在您的操作方法中显式链接,您可以编写各种不同的行为来生成您的响应。

 // this will return HttpResponseMessage as IHttpActionResult return ResponseMessage(httpResponseMessage); 

以下是在Microsoft ASP.Net文档中提到的HttpResponseMessageIHttpActionResult几个好处:

  • 简化unit testing您的控制器。
  • 将用于创buildHTTP响应的通用逻辑移到不同的类中。
  • 通过隐藏构build响应的底层细节使控制器动作的意图更清晰。

但是使用IHttpActionResult还有其他一些优点值得一提:

  • 遵守单一职责原则 :使得操作方法有责任为HTTP请求提供服务,而不涉及创buildHTTP响应消息。
  • 已经在System.Web.Http.Results中定义了有用的实现 ,即: Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState ( 链接到完整列表 )
  • 默认情况下使用asynchronous和等待
  • 只需执行ExecuteAsync方法即可轻松创build自己的ActionResult
  • 您可以使用ResponseMessageResult ResponseMessage(HttpResponseMessage response) 将HttpResponseMessage转换为IHttpActionResult

这只是我的个人意见,Web API团队的人可能会更好地expression它,但这里是我的2c。

首先,我认为这不是一个又一个的问题。 你可以使用它们,这取决于你想要在你的action方法中做什么,但为了理解IHttpActionResult的真正威力,你可能需要在ApiController方便的帮助器方法ApiController例如OkNotFound等。

基本上,我认为一个类实现IHttpActionResult作为HttpResponseMessage的工厂。 随着这个思维定势,它现在成为一个需要被退回的对象和一个产生它的工厂。 在一般的编程意义上,你可以在某些情况下自己创build对象,在某些情况下,你需要一个工厂来做到这一点。 同样在这里。

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

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

当然,正如Darrel指出的那样,您可以链接操作结果,并在APIpipe道中创build一个类似于消息处理程序的强大的微pipe道。 这将取决于您的操作方法的复杂性。

长话短说 – 这不是IHttpActionResultHttpResponseMessage 。 基本上,这是你想如何创build响应。 自己做或者通过工厂做。

WebAPI基本上返回4种types的对象:void,HttpResponseMessage,IHttpActionResult和其他强types。 首先版本WebAPI返回HttpResponseMessage,这是非常简单的HTTP响应消息。

IHttpActionResult是由WebAPI 2引入的,它是HttpResponseMessage的一种包装。 它包含ExecuteAsync方法来创build一个HttpResponseMessage。 它简化了您的控制器的unit testing。

其他的返回types是通过Web API使用媒体格式化程序连接到响应主体的强types类。 缺点是你不能直接返回错误代码,比如404。你所能做的就是抛出一个HttpResponseException错误。

我宁愿为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是有效载荷。

通过HttpResponseMessage使用IhttpActionResult有以下好处

  1. 通过使用IhttpActionResult,我们只关注要发送的数据而不是状态码。 所以这里的代码会更干净,更容易维护。
  2. unit testing实现的控制器方法将会更容易。
  3. 使用asynchronous和默认等待。