c# - net - ¿Cuál es la diferencia entre HttpResponseMessage y HttpResponseException?
web api rest c# (5)
Como dicen las preguntas originales, no hay una diferencia real en la Respuesta devuelta.
El objetivo real de HttpResponseException es permitir que los submétodos creen y "arrojen" sus propios HttpResponseMessages que fluyan de regreso a la pila de llamadas y se devuelvan al cliente.
public class CustomerController : ApiController {
private ICustomerContext repo;
public CustomerController(ICustomerContext repo) {
this.repo = repo;
}
public HttpResponseMessage Get(int id) {
Customer customer = getCustomer(id);
return Request.CreateResponse(customer);
}
private Customer getCustomer(int id){
.....do some work
.....we have a problem so throw exception
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest, "Id out of range");
return repo.Customers.SingleOrDefault(c=>c.CustomerID == id)
}
Perdona cualquier error, código escrito sobre la marcha. La HttpResponseException lanzada surge a través de la pila de llamadas de acciones, no queda atrapada por los manejadores de Excepciones normales y devuelve su HttpResponseMessage como lo haría el método de acción en sí.
Traté de entender ambos y escribir código de muestra:
public HttpResponseMessage Get()
{
var response = ControllerContext.Request
.CreateResponse(HttpStatusCode.BadRequest, "abc");
throw new HttpResponseException(response);
}
Y:
public HttpResponseMessage Get()
{
return ControllerContext.Request
.CreateResponse(HttpStatusCode.BadRequest, "abc");
}
Desde Fiddle, realmente no vi ninguna diferencia entre ellos, ¿cuál es el propósito de usar HttpResponseException
?
HttpResponseException es útil cuando la firma de la acción del controlador se parece a
Foo Get(int id)
En este caso, no puede devolver fácilmente el código de estado como 400.
Tenga en cuenta que HttpResponseMessage<T>
desaparecerá en la próxima versión de Web API.
La principal diferencia entre los dos es esto. La excepción es útil para detener el procesamiento y salir inmediatamente. Por ejemplo, supongamos que tengo el siguiente código
public class CustomerController : ApiController {
private ICustomerContext repo;
public CustomerController(ICustomerContext repo) {
this.repo = repo;
}
public Customer Get(int id) {
var customer = repo.Customers.SingleOrDefault(c=>c.CustomerID == id);
if (customer == null) {
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
return customer;
}
}
Si se ejecuta este código y paso una identificación que no está presente, se detendrá inmediatamente el procesamiento y se devolverá un código de estado de 404.
Si, en cambio, devuelvo HttpResponseMessage, la solicitud continuará felizmente el resto de su procesamiento y devolverá un 404. La principal diferencia es que finalice o no la solicitud.
Como dijo Darrel, la excepción es útil en casos en los que, en algunos casos, quiero que el procesamiento continúe (como cuando se encuentra al cliente) y en otros no.
El lugar donde es posible que desee utilizar algo como HttpResponseMessage está en un Http POST para devolver un código de estado de 201 y establecer el encabezado de ubicación. En ese caso, quiero que el procesamiento continúe. Eso haría con este código. *
public class CustomerController : ApiController {
private ICustomerContext repo;
public CustomerController(ICustomerContext repo) {
this.repo = repo;
}
public HttpResponseMessage Post(Customer customer) {
repo.Add(customer);
repo.SaveChanges();
var response = Request.CreateResponse(HttpStatusCode.Created, customer);
response.Headers.Location = new Uri(Request.RequestUri, string.format("customer/{0}", customer.id));
return response;
}
}
* nota: si está utilizando los bits beta, crearía un nuevo HttpResponseMessage. Sin embargo, estoy usando las últimas partes que requieren que uses el método de extensión CreateResponse fuera de la Solicitud.
Arriba, estoy creando una respuesta que establece el código de estado en 201, pasa al cliente y luego establece el encabezado de ubicación.
La respuesta se devuelve y la solicitud continúa procesándose.
Espero que esto ayude
Suponiendo que desea probar las respuestas, ¿no tiene sentido devolver siempre un HttpResponseMessage? No me gusta particularmente la idea de devolver un tipo recto de un ApiController ya que no sigue los patrones de desarrollo típicos.
En una clase API que no sea Web que haya obtenido un Cliente, es probable que devuelva un valor nulo, con su código de llamada buscando una respuesta nula:
public Customer GetCustomer(int id)
{
return db.Customers.Find(id);
}
Pero en Web API, no va a devolver nulo, tiene que devolver algo, incluso si ese algo se crea después de lanzar una HttpResponseException. En ese caso, para facilitar las pruebas, ¿por qué no siempre devuelve un HttpResponseMessage y lo convierte en su firma?
public HttpResponseMessage GetCustomer(int id)
{
var customer = db.Customers.Find(id);
if (customer == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
return Request.CreateResponse(HttpStatusCode.OK, customer);
}
HttpResponseException
deriva de Exception
e incorpora HttpResponseMessage
. Como deriva de Exception
, puede ser útil en escenarios de try
y catch
.
El código de estado predeterminado devuelto por HttpResponseException
es HttpStatusCode.InternalServerError
.