c# - example - ¿Por qué debo usar IHttpActionResult en lugar de HttpResponseMessage?
unauthorized ihttpactionresult (8)
He estado desarrollando con WebApi y pasé a WebApi2, donde Microsoft ha introducido una nueva Interfaz IHttpActionResult
que parece ser recomendada para usar sobre la devolución de un HttpResponseMessage
. Estoy confundido sobre las ventajas de esta nueva interfaz. Parece que, principalmente, solo proporciona una manera LIGERAMENTE más fácil de crear un HttpResponseMessage
.
Yo diría que esto es "abstracción en aras de la abstracción". ¿Me estoy perdiendo de algo? ¿Cuáles son las ventajas del mundo real que obtengo al usar esta nueva Interfaz además de guardar una línea de código?
Camino antiguo (WebApi):
public HttpResponseMessage Delete(int id)
{
var status = _Repository.DeleteCustomer(id);
if (status)
{
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
Nueva forma (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();
}
}
Aquí hay varios beneficios de IHttpActionResult
over HttpResponseMessage
mencionados en la documentación de Microsoft ASP.Net :
- Simplifica la unidad de pruebas de sus controladores.
- Mueve la lógica común para crear respuestas HTTP en clases separadas.
- Aclara la intención de la acción del controlador al ocultar los detalles de bajo nivel de la construcción de la respuesta.
Pero aquí hay algunas otras ventajas de usar IHttpActionResult
vale la pena mencionar:
- Respetar el principio de responsabilidad única : hacer que los métodos de acción tengan la responsabilidad de atender las solicitudes HTTP y no los involucra en la creación de los mensajes de respuesta HTTP.
- Implementaciones útiles ya definidas en System.Web.Http.Results a saber:
Ok
NotFound
Exception
Unauthorized
BadRequest
Conflict
Redirect
InvalidModelState
( enlace a la lista completa ) - Utiliza Async y Espera por defecto.
- Fácil de crear su propio ActionResult simplemente implementando el método
ExecuteAsync
. - puede usar
ResponseMessageResult ResponseMessage(HttpResponseMessage response)
para convertir HttpResponseMessage en IHttpActionResult .
Esta es solo mi opinión personal y la gente del equipo de la API web probablemente pueda articularlo mejor, pero aquí está mi 2c.
En primer lugar, creo que no se trata de uno sobre el otro. Puede usarlos en función de lo que desee hacer en su método de acción, pero para comprender el poder real de IHttpActionResult
, probablemente deba ApiController
de los métodos de ayuda de ApiController
como Ok
, NotFound
, etc.
Básicamente, creo que una clase que implementa IHttpActionResult
como una fábrica de HttpResponseMessage
. Con esa mentalidad, ahora se convierte en un objeto que debe devolverse y en una fábrica que lo produce. En el sentido general de la programación, puede crear el objeto usted mismo en ciertos casos y en ciertos casos, necesita una fábrica para hacerlo. Igual que aquí.
Si desea devolver una respuesta que deba construirse a través de una lógica compleja, digamos muchos encabezados de respuesta, etc., puede abstraer toda esa lógica en una clase de resultado de acción implementando IHttpActionResult
y usarla en múltiples métodos de acción para devolver la respuesta.
Otra ventaja de usar IHttpActionResult
como tipo de retorno es que hace que el método de acción de la API web de ASP.NET sea similar a MVC. Puedes devolver cualquier resultado de acción sin que te atrapen los formateadores de medios.
Por supuesto, como señala Darrel, puede encadenar resultados de acción y crear un micro-canalización potente similar a los controladores de mensajes en el canal de API. Esto necesitarás dependiendo de la complejidad de tu método de acción.
Larga historia corta: no es IHttpActionResult
versus HttpResponseMessage
. Básicamente, es cómo quieres crear la respuesta. Hazlo tú mismo oa través de una fábrica.
La API web básicamente devuelve 4 tipos de objeto: void
, HttpResponseMessage
, IHttpActionResult
y otros tipos fuertes. La primera versión de la API web devuelve HttpResponseMessage
que es un mensaje de respuesta HTTP bastante sencillo.
El IHttpActionResult
fue introducido por WebAPI 2, que es un tipo de envoltura de HttpResponseMessage
. Contiene el método ExecuteAsync()
para crear un HttpResponseMessage
. Simplifica las pruebas unitarias de su controlador.
Otros tipos de retorno son clases de tipo tipificado fuerte serializadas por la API web utilizando un formateador de medios en el cuerpo de la respuesta. El inconveniente fue que no puede devolver directamente un código de error como el 404. Todo lo que puede hacer es lanzar un error HttpResponseException
.
Prefiero implementar la función de interfaz TaskExecuteAsync para IHttpActionResult. Algo como:
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);
}
, donde _request es HttpRequest y _respContent es la carga útil.
Puede decidir no usar IHttpActionResult
porque su código existente genera un HttpResponseMessage
que no se ajusta a una de las respuestas enlatadas. Sin embargo, puede adaptar HttpResponseMessage
a IHttpActionResult
utilizando la respuesta enlatada de ResponseMessage
. Me tomó un tiempo resolver esto, así que quería publicarlo mostrando que no necesariamente tienes que elegir uno u otro:
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;
}
Tenga en cuenta que ResponseMessage
es un método de la clase base ApiController
que su controlador debería heredar.
Tenemos los siguientes beneficios de usar IHttpActionResult
over HttpResponseMessage
:
- Al utilizar
IHttpActionResult
, solo nos concentramos en los datos que se enviarán, no en el código de estado. Así que aquí el código será más limpio y muy fácil de mantener. - Las pruebas unitarias del método del controlador implementado serán más fáciles.
- Utiliza
async
yawait
por defecto.
Todavía puede utilizar HttpResponseMessage
. Esa capacidad no desaparecerá. Sentí lo mismo que tú y discutí ampliamente con el equipo que no había necesidad de una abstracción adicional. Hubo algunos argumentos para intentar justificar su existencia, pero nada me convenció de que valía la pena.
Es decir, hasta que vi this muestra de Brad Wilson . Si construye IHttpActionResult
clases IHttpActionResult
de una manera que se puede encadenar, obtiene la capacidad de crear una línea de respuesta de "nivel de acción" para generar el HttpResponseMessage
. Bajo las carátulas, así es como se implementan los ActionFilters
, sin embargo, el orden de esos ActionFilters
no es obvio cuando se lee el método de acción, que es una de las razones por las que no soy fanático de los filtros de acción.
Sin embargo, al crear un IHttpActionResult
que puede ser encadenado explícitamente en su método de acción, puede componer todo tipo de comportamiento diferente para generar su respuesta.
// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage);