Почему я должен использовать IHttpActionResult вместо HttpResponseMessage?

Я развиваюсь с помощью WebApi и перешел на WebApi2, где Microsoft представила новый IHttpActionResult интерфейс, который, как представляется, рекомендуется использовать для возврата HttpResponseMessage. Я смущен преимуществами этого нового интерфейса. Похоже, что в основном просто создать SLIGHTLY более простой способ создания 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();
    }
}

Ответ 1

Вы можете не использовать IHttpActionResult, потому что ваш существующий код создает HttpResponseMessage, который не соответствует одному из сохраненных ответов. Однако вы можете адаптировать HttpResponseMessage к IHttpActionResult с помощью консервированного ответа ResponseMessage. Мне потребовалось некоторое время, чтобы понять это, поэтому я хотел опубликовать его, показывая, что вам необязательно выбирать тот или иной:

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, который должен наследовать ваш контроллер.

Ответ 2

Вы все еще можете использовать HttpResponseMessage. Эта способность не исчезнет. Я чувствовал то же самое, что и вы, и активно советовал команде, что нет необходимости в дополнительной абстракции. Было несколько аргументов, которые пытались оправдать его существование, но ничто не убеждало меня, что это стоит того.

То есть, пока я не увидел этот образец от Брэда Уилсона. Если вы IHttpActionResult классы IHttpActionResult таким образом, чтобы их можно было сковать, вы получаете возможность создавать конвейер ответа "уровень действия" для генерации HttpResponseMessage. Тем не менее, под ActionFilters реализовано действие ActionFilters поэтому порядок этих ActionFilters не является очевидным при чтении метода действия, который является одной из причин, по которым я не являюсь поклонником фильтров действий.

Однако, создав IHttpActionResult который может быть явно IHttpActionResult в вашем методе действий, вы можете создавать различные виды поведения для генерации вашего ответа.

Ответ 3

Вот несколько преимуществ IHttpActionResult over HttpResponseMessage, упомянутых в Документация Microsoft ASP.Net:

  • Упрощает модульное тестирование ваших контроллеров.
  • Перемещает общую логику для создания ответов HTTP в отдельные классы.
  • Делает задачу действий контроллера более ясной, скрывая детали низкого уровня построения ответа.

Но вот некоторые другие преимущества использования IHttpActionResult, которые стоит упомянуть:

  • Соблюдение принципа единой ответственности: заставляйте методы действий отвечать за обслуживание HTTP-запросов и не привлекать их к созданию сообщений ответа HTTP.
  • Полезные реализации, уже определенные в System.Web.Http.Results, а именно: Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState (ссылка на полный список)
  • По умолчанию используется Async и Await.
  • Просто создать собственный ActionResult, просто используя метод ExecuteAsync.
  • вы можете использовать ResponseMessageResult ResponseMessage(HttpResponseMessage response) для конвертировать HttpResponseMessage в IHttpActionResult.

Ответ 4

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

Ответ 5

Это только мое личное мнение, и люди из команды веб-API могут, возможно, сформулировать это лучше, но вот мой 2c.

Прежде всего, я думаю, что это не вопрос одного над другим. Вы можете использовать их в зависимости от того, что вы хотите сделать в своем методе действий, но для того, чтобы понять реальную мощность IHttpActionResult, вам, вероятно, придется выйти за пределы тех удобных вспомогательных методов ApiController, таких как Ok, NotFound и т.д.

В принципе, я считаю класс, реализующий IHttpActionResult как factory HttpResponseMessage. С этим набором разума он теперь становится объектом, который необходимо вернуть, и создающим его factory. В общем смысле программирования вы можете сами создать объект в определенных случаях, и в некоторых случаях вам понадобится factory. То же самое здесь.

Если вы хотите вернуть ответ, который должен быть сконструирован с помощью сложной логики, скажем много заголовков ответов и т.д., вы можете абстрагировать всю эту логику в класс результата выполнения, реализующий IHttpActionResult, и использовать его в нескольких методах действий для ответа.

Другим преимуществом использования IHttpActionResult как типа возврата является то, что он делает метод действия ASP.NET Web API аналогичным MVC. Вы можете вернуть любой результат действия, не попадая в медиаформаты.

Конечно, как отметил Даррел, вы можете связать результаты действий и создать мощный микропровод, похожий на обработчики сообщений в конвейере API. Это вам потребуется в зависимости от сложности вашего метода действий.

Короче говоря - это не IHttpActionResult против HttpResponseMessage. В принципе, именно так вы хотите создать ответ. Сделайте это самостоятельно или через factory.

Ответ 6

Веб-API в основном возвращает 4 типа объекта: void, HttpResponseMessage, IHttpActionResult и другие сильные типы. Первая версия веб-API возвращает HttpResponseMessage который является довольно прямым ответом HTTP-ответа.

IHttpActionResult был представлен WebAPI 2, который является своего рода переносом HttpResponseMessage. Он содержит метод ExecuteAsync() для создания HttpResponseMessage. Это упрощает модульное тестирование вашего контроллера.

Другой тип возвращаемого типа - это типичные типизированные классы, сериализованные веб-API с использованием медиаформата в тело ответа. Недостатком было то, что вы не можете напрямую вернуть код ошибки, такой как 404. Все, что вы можете сделать, это выбросить ошибку HttpResponseException.

Ответ 7

Я предпочел бы реализовать функцию интерфейса TaskExecuteAsync для IHttpActionResult. Что-то вроде:

    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:

  1. Используя IHttpActionResult мы концентрируемся только на данных, которые будут отправляться не на код состояния. Таким образом, здесь код будет более чистым и очень прост в обслуживании.
  2. Групповое тестирование внедренного контроллера будет проще.
  3. Использует async и await по умолчанию.