为什么我应该使用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文档中提到的HttpResponseMessage
的IHttpActionResult
几个好处:
- 简化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
例如Ok
, NotFound
等。
基本上,我认为一个类实现IHttpActionResult
作为HttpResponseMessage
的工厂。 随着这个思维定势,它现在成为一个需要被退回的对象和一个产生它的工厂。 在一般的编程意义上,你可以在某些情况下自己创build对象,在某些情况下,你需要一个工厂来做到这一点。 同样在这里。
如果你想返回一个需要通过一个复杂的逻辑来构造的响应,比如很多的响应头等等,你可以将所有这些逻辑抽象成一个实现IHttpActionResult
的动作结果类,并在多个动作方法中使用它来返回响应。
使用IHttpActionResult
作为返回types的另一个优点是它使ASP.NET Web API的操作方法类似于MVC。 您可以返回任何操作结果,而不会被媒体格式化程序捕获。
当然,正如Darrel指出的那样,您可以链接操作结果,并在APIpipe道中创build一个类似于消息处理程序的强大的微pipe道。 这将取决于您的操作方法的复杂性。
长话短说 – 这不是IHttpActionResult
与HttpResponseMessage
。 基本上,这是你想如何创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有以下好处
- 通过使用IhttpActionResult,我们只关注要发送的数据而不是状态码。 所以这里的代码会更干净,更容易维护。
- unit testing实现的控制器方法将会更容易。
- 使用asynchronous和默认等待。
- ASP.NET Web API 2:如何使用外部authentication服务login?
- 错误:请求标头字段Content-Type不被Access-Control-Allow-Headers所允许
- 无法使用Json序列化Web API中的响应
- 找不到Request.GetOwinContext
- ASP.NET Core 1.0 Web API中的简单JWT身份validation
- 如何返回错误消息或exceptionNotFound()IHttpActionResult?
- 如何在WebAPI 2中进行CORS身份validation?
- 如何在EF中更新父实体时添加/更新子实体
- 当ID包含句点时,ApiController返回404