我一直在用WebApi开发,已经转移到WebApi2,微软已经引入了一个新的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();
    }
}

当前回答

使用IHttpActionResult而不是HttpResponseMessage有以下好处:

通过使用IHttpActionResult,我们只关注要发送的数据,而不是状态码。所以这里的代码会更简洁,也更容易维护。 实现的控制器方法的单元测试将更容易。 默认使用async和await。

其他回答

您可能决定不使用IHttpActionResult,因为您现有的代码构建了一个HttpResponseMessage,该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的一个方法。

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

使用IHttpActionResult而不是HttpResponseMessage有以下好处:

通过使用IHttpActionResult,我们只关注要发送的数据,而不是状态码。所以这里的代码会更简洁,也更容易维护。 实现的控制器方法的单元测试将更容易。 默认使用async和await。

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

首先,我认为这不是一个人胜过另一个人的问题。你可以使用它们,这取决于你想在你的动作方法中做什么,但为了理解IHttpActionResult的真正力量,你可能需要走出ApiController的那些方便的帮助方法,如Ok, NotFound,等等。

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

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

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

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

长话短说——它不是IHttpActionResult和HttpResponseMessage。基本上,这是你想要创建响应的方式。你可以自己做,也可以去工厂做。

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