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

我认为这是“抽象的抽象”。我想念什么吗?除了可能节省一行代码之外,使用此新接口还能为我带来现实的好处吗? />新方法(WebApi2):

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


评论

我刚刚发现了一些有趣的东西。我不确定这些结果是否可以被其他人验证。但是通过执行一些调用,性能有了很大提高:*通过使用HttpResponseMessage的示例,我在9545 ms内获得了响应。 *使用IHttpActionResult,我在294毫秒内得到了相同的响应。

@chrislesage 9545毫秒将近10秒。即使是294ms也有点慢。如果您花费的时间超过100毫秒,那么那里还有其他工作。这个故事比见识到的还要重要。

#1 楼

您可能决定不使用IHttpActionResult,因为您现有的代码会生成一个HttpResponseMessage,它不符合罐装响应之一。但是,您可以使用HttpResponseMessage的固定响应将IHttpActionResult调整为ResponseMessage。我花了一些时间才弄清楚这一点,因此我想发布它,以表明您不必选择其中一个: ResponseMessage是控制器应从其继承的基类ApiController的方法。

评论


花了我一段时间才发现ResponseMessage现在是ResponseMessageResult。也许它最近已重命名?附言您还错过了答案中的新关键字,非常感谢您的建议:)

–伊利亚·切尔诺莫迪克(Ilya Chernomordik)
2015年2月6日15:14



@IlyaChernomordik ResponseMessage和ResponseMessageResult是两个不同的事物。 ResponseMessage()是控制器应从其继承的ApiController的方法,因此仅是方法调用。因此,那里不需要新的关键字。您可能没有从ApiController继承,或者您处于静态方法内。 ResponseMessageResult是ResponseMessage()的返回类型。

– AaronLS
2015年2月6日,19:10

@IlyaChernomordik我可以写出response = base.ResponseMessage(responseMsg),以使其更清楚地表明它是基类ApiController的方法

– AaronLS
15年2月6日在19:12

谢谢,我确实有一个服务没有从ApiController继承,这就是为什么要花一些时间才能找到它的原因。

–伊利亚·切尔诺莫迪克(Ilya Chernomordik)
2015年2月9日在9:24



@pootzko您说得对,我提到了一个事实,即OP似乎暗示他们认为这两种方法是互斥的,将它们称为“旧方法”与“新方法”,而实际上并非如此。我认为Darrel的答案很好地解释了返回IHttpActionResult的一些好处,并且我的答案演示了如何将旧的HttpResponseMessage转换为IHttpActionResult,从而可以兼得两者。

– AaronLS
15年5月26日在0:09

#2 楼

您仍然可以使用HttpResponseMessage。这种能力不会消失。我的感觉和您一样,并与团队进行了广泛的辩论,认为不需要其他抽象。有一些争论试图证明它的存在,但是没有什么使我确信它是值得的。

,直到我看到布拉德·威尔逊的这个样本。如果以可链接的方式构造IHttpActionResult类,则可以创建“操作级”响应管道以生成HttpResponseMessage的功能。在幕后,这是ActionFilters的实现方式,但是,在阅读action方法时,ActionFilters的顺序并不明显,这是我不喜欢action filter的原因之一。创建一个可以在您的操作方法中显式链接的IHttpActionResult,您可以组合各种不同的行为来生成您的响应。

#3 楼

这是IHttpActionResult优于Microsoft ASP.Net文档中提到的HttpResponseMessage的几个优点:



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



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



指定单一责任原则:导致操作方法负责服务HTTP请求,并且不参与创建HTTP响应消息。

System.Web.Http。中已经定义的有用实现,结果是:Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState(链接到完整列表)
默认情况下使用Async和Await。 br />
只需实现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。您可以返回任何操作结果,而不会陷入媒体格式化程序中。 。取决于您的操作方法的复杂性。

长话短说-它不是IHttpActionResultHttpResponseMessage。基本上,这就是您要如何创建响应。自己或通过工厂进行。

评论


我在工厂调整中遇到的问题是,我可以轻松地创建返回HttpResponseMessage的静态方法(如ResponseFactory.CreateOkResponse()),并且在创建响应时不必处理异步内容。一位团队成员确实提到了以下事实:如果您需要执行I / O来生成标头值,那么异步可能会很有用。虽然不确定发生的频率。

– Darrel Miller
14年2月13日在17:32

我认为这与说为什么我们需要工厂方法模式相同。为什么不只是使用静态方法来创建对象。当然,这是可行的-每个对象创建都不具有适当的工厂模式。但是恕我直言,这取决于您要如何对类进行建模。您是否想要逻辑来创建不同类型的响应,这些响应都以多种静态方法的形式塞入一个类,或者具有基于接口的不同类。同样,没有好与坏。一切都取决于。无论如何,我的观点是,这不是一个相互重叠的过程,我个人更喜欢工厂的东西:)

–巴德里
14年2月13日在17:53

#6 楼

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

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

其他返回类型是由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 楼

与使用IHttpActionResult相比,使用HttpResponseMessage有以下好处:通过使用IHttpActionResult,我们只专注于要发送的数据,而不关注状态码。因此,这里的代码将更加整洁,并且易于维护。
实现的控制器方法的单元测试将更加容易。
默认情况下使用asyncawait