2014-02-13 376 views
242

我一直的WebAPI开发,并已转移到WebApi2,微软又推出了新的IHttpActionResult接口,这似乎建议在返回HttpResponseMessage使用。我很困惑这个新界面的优点。它似乎主要只是提供一个更简单的方法来创建HttpResponseMessage为什么我应该使用IHttpActionResult而不是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(); 
    } 
} 

回答

229

您可能决定不使用IHttpActionResult,因为您现有的代码构建的HttpResponseMessage不适合其中一个预设响应。然而,您可以使用ResponseMessage的罐头响应将HttpResponseMessage改为IHttpActionResult。我花了一段时间来弄清楚这一点,所以我想将它张贴表明你没有necesarily必须选择一个或其他:

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的方法,你的控制器应该继承自。

+1

花了我一会儿,找出ResponseMessage现在是ResponseMessageResult。最近它可能已经改名了吗?附:你也错过了答案中的新关键字,并非常感谢你的建议:) –

+7

@IlyaChernomordik'ResponseMessage'和'ResponseMessageResult'是两个不同的东西。 ResponseMessage()是你的控制器应该继承的ApiController的一个*方法,因此只是一个方法调用。所以在那里不需要'new'关键字。你可能不是从'ApiController'继承,或者你在一个静态方法中。 'ResponseMessageResult'是'ResponseMessage()'的返回类型。 – AaronLS

+2

@IlyaChernomordik我可以写出'response = base.ResponseMessage(responseMsg)'使它更清楚它是基类的一个方法ApiController – AaronLS

73

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

也就是说,直到我看到this样本布拉德威尔逊。如果您构建可链接的方式IHttpActionResult类,您将获得创建“动作级”响应管道用于生成HttpResponseMessage的能力。在封面下,这是ActionFilters的实现方式,但是在阅读操作方法时这些ActionFilters的顺序并不明显,这是我不是操作过滤器粉丝的原因之一。

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

12

这只是我个人的意见,并从网络API团队乡亲大概可以更好地表达,但这里是我2C。

首先,我想是不是一个对另一个的问题。您可以使用这两个取决于你想要在你的操作方法做什么,但为了了解IHttpActionResult真正的力量,你可能需要加强的,如OkNotFoundApiController这些方便的辅助方法外,等

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

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

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

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

长话短说 - 它不是IHttpActionResultHttpResponseMessage。基本上,它是如何创建响应。自己做或者通过工厂做。

+0

我与工厂一起工作的问题是,我可以很容易地创建像ResponseFactory.CreateOkResponse()这样的返回HttpResponseMessage的静态方法,并且我在创建响应时不必处理异步内容。一位团队成员确实提到了如果您需要执行I/O以生成标题值,则异步可能很有用。不知道这种情况发生的频率。 –

+0

我认为这与我们为什么需要工厂方法模式相同。为什么不使用静态方法来创建对象。当然,这是可行的 - 每个对象的创建都不适合合适的工厂模式。但是,恕我直言,这取决于你想如何建模你的类。你是否想要创建逻辑来创建不同类型的响应,这些响应以多个静态方法的形式挤入类中,或者基于接口具有不同的类。再次,没有好或坏。这完全取决于。无论如何,我的观点是,它不是一个超过另一个,我个人喜欢工厂的东西更好:) – Badri

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

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

4

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

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

其他返回类型是Web API使用媒体格式化程序将序列化为强类型的类放入响应主体。缺点是你不能直接返回错误代码,比如404.你所能做的就是抛出一个HttpResponseException错误。

32

这里是IHttpActionResult在以上提到的Microsoft ASP.Net Documentation几个HttpResponseMessage好处:

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

但这里有使用IHttpActionResult值得一提的其他一些优点:

  • 尊重单一职责原则:案由方法有服务于HTTP请求的责任,不涉及他们在创建HTTP响应消息。
  • 有用的实现中即System.Web.Http.Results已经定义:OkNotFoundExceptionUnauthorizedBadRequestConflictRedirectInvalidModelStatelink to full list
  • 默认使用异步和等待
  • 只需执行ExecuteAsync方法即可轻松创建自己的ActionResult
  • 您可以使用ResponseMessageResult ResponseMessage(HttpResponseMessage response)将HttpResponseMessage转换为IHttpActionResult
0

我们使用IHttpActionResultHttpResponseMessage的以下优点:

  1. 通过使用IHttpActionResult我们只专注于数据要发送不在状态代码。所以这里的代码会更干净并且很容易维护。
  2. 实施的控制器方法的单元测试将更容易。
  3. 默认使用asyncawait
相关问题