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

Я развиваюсь с помощью WebApi и перешел на WebApi2, где Microsoft представила новый интерфейс 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 , который не соответствует одному из законченных ответов. Тем не менее, вы можете адаптировать 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 – это метод базового classа ApiController который должен наследовать ваш controller.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  public Task 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 – полезная нагрузка.

Мы имеем следующие преимущества использования IHttpActionResult над HttpResponseMessage :

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