Me preocupa la forma en que devolvemos los errores al cliente.
¿Devuelve el error de inmediato lanzando HttpResponseException cuando recibimos un error:
public void Post(Customer customer)
{
if (string.IsNullOrEmpty(customer.Name))
{
throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
}
if (customer.Accounts.Count == 0)
{
throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest)
}
}
O acumulamos todos los errores y luego los enviamos de vuelta al cliente:
public void Post(Customer customer)
{
List<string> errors = new List<string>();
if (string.IsNullOrEmpty(customer.Name))
{
errors.Add("Customer Name cannot be empty");
}
if (customer.Accounts.Count == 0)
{
errors.Add("Customer does not have any account");
}
var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
throw new HttpResponseException(responseMessage);
}
Este es solo un código de muestra, no importa ni los errores de validación ni los errores del servidor, solo me gustaría conocer las mejores prácticas, los pros y los contras de cada enfoque.
c#
rest
asp.net-web-api
cuongle
fuente
fuente
ModelState
.HttpResponseException
clase que tome dos parámetros mencionados en su publicación,HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest)
es decirHttpResponseException(string, HttpStatusCode)
Respuestas:
Para mí, generalmente envío de vuelta
HttpResponseException
y configuro el código de estado en consecuencia, dependiendo de la excepción lanzada y si la excepción es fatal o no, determinaré si devuelvo elHttpResponseException
inmediatamente.Al final del día, es una API que envía respuestas y no vistas, así que creo que está bien enviar un mensaje con el código de excepción y estado al consumidor. Actualmente no he necesitado acumular errores y enviarlos de regreso, ya que la mayoría de las excepciones generalmente se deben a parámetros o llamadas incorrectas, etc.
Un ejemplo en mi aplicación es que a veces el cliente pedirá datos, pero no hay datos disponibles, por lo que lanzo un mensaje personalizado
NoDataAvailableException
y lo dejo en la aplicación API web, donde luego en mi filtro personalizado que captura el envío de un mensaje relevante junto con el código de estado correcto.No estoy 100% seguro de cuál es la mejor práctica para esto, pero esto está funcionando para mí actualmente, así que eso es lo que estoy haciendo.
Actualización :
Desde que respondí esta pregunta, se han escrito algunas publicaciones de blog sobre el tema:
https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling
(este tiene algunas características nuevas en las versiones nocturnas) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi
Actualización 2
Actualización de nuestro proceso de manejo de errores, tenemos dos casos:
Para errores generales como no encontrado, o parámetros no válidos que se pasan a una acción, devolvemos a
HttpResponseException
para detener el procesamiento de inmediato. Además, para errores de modelo en nuestras acciones, entregaremos el diccionario de estado del modelo a laRequest.CreateErrorResponse
extensión y lo envolveremos en aHttpResponseException
. Agregar el diccionario de estado del modelo da como resultado una lista de los errores del modelo enviados en el cuerpo de la respuesta.Para los errores que se producen en capas superiores, errores del servidor, dejamos que la excepción aparezca en la aplicación API web, aquí tenemos un filtro de excepción global que analiza la excepción, la registra con ELMAH e intenta que tenga sentido establecer la HTTP correcta código de estado y un mensaje de error amigable relevante como el cuerpo nuevamente en a
HttpResponseException
. Para las excepciones que no esperamos que el cliente reciba el error predeterminado del servidor interno 500, sino un mensaje genérico debido a razones de seguridad.Actualización 3
Recientemente, después de elegir Web API 2, para enviar errores generales, ahora usamos la interfaz IHttpActionResult , específicamente las clases integradas para en el
System.Web.Http.Results
espacio de nombres como NotFound, BadRequest cuando encajan, si no es así, las extendemos, por ejemplo Un resultado NotFound con un mensaje de respuesta:fuente
ASP.NET Web API 2 realmente lo simplificó. Por ejemplo, el siguiente código:
devuelve el siguiente contenido al navegador cuando no se encuentra el elemento:
Sugerencia: No arroje HTTP Error 500 a menos que haya un error catastrófico (por ejemplo, WCF Fault Exception). Elija un código de estado HTTP apropiado que represente el estado de sus datos. (Vea el enlace de apigee a continuación).
Enlaces:
fuente
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
Cuál es la diferencia entreCreateResponse
y?CreateErrorResponse
using System.Net.Http;
para elCreateResponse()
método de extensión en aparecer.Parece que tienes más problemas con la validación que con los errores / excepciones, así que diré un poco sobre ambos.
Validación
Las acciones del controlador generalmente deben tomar Modelos de entrada donde la validación se declara directamente en el modelo.
Luego puede usar un
ActionFilter
que envía automáticamente mensajes de validación al cliente.Para obtener más información sobre esto, visite http://ben.onfabrik.com/posts/automatic-modelstate-validation-in-aspnet-mvc
Manejo de errores
Es mejor devolver un mensaje al cliente que represente la excepción que sucedió (con el código de estado relevante).
Fuera de la caja que debe usar
Request.CreateErrorResponse(HttpStatusCode, message)
si desea especificar un mensaje. Sin embargo, esto vincula el código alRequest
objeto, lo que no debería necesitar hacer.Por lo general, creo mi propio tipo de excepción "segura" que espero que el cliente sepa cómo manejar y envolver a todos los demás con un error genérico 500.
Usar un filtro de acción para manejar las excepciones se vería así:
Entonces puedes registrarlo globalmente.
Este es mi tipo de excepción personalizado.
Una excepción de ejemplo que mi API puede lanzar.
fuente
var exception = context.Exception as WebException;
eso fue un error tipográfico, debería haber sidoApiException
Puedes lanzar una HttpResponseException
fuente
Para Web API 2, mis métodos devuelven constantemente IHttpActionResult, así que uso ...
fuente
System.Net.Http
Si está utilizando ASP.NET Web API 2, la forma más fácil es utilizar el método abreviado ApiController. Esto dará como resultado un BadRequestResult.
fuente
return BadRequest(ModelState);
puede usar ActionFilter personalizado en Web Api para validar el modelo
}
Registre la clase CustomAttribute en webApiConfig.cs config.Filters.Add (new DRFValidationFilters ());
fuente
A partir
Manish Jain
de la respuesta (que está diseñada para Web API 2 que simplifica las cosas):1) Use estructuras de validación para responder tantos errores de validación como sea posible. Estas estructuras también se pueden utilizar para responder a solicitudes provenientes de formularios.
2) La capa de servicio devolverá
ValidationResult
s, independientemente de que la operación sea exitosa o no. P.ej:3) API Controller construirá la respuesta en función del resultado de la función de servicio
Una opción es colocar virtualmente todos los parámetros como opcionales y realizar una validación personalizada que devuelva una respuesta más significativa. Además, me aseguro de no permitir que ninguna excepción vaya más allá del límite del servicio.
fuente
Utilice el método incorporado "InternalServerError" (disponible en ApiController):
fuente
Solo para actualizar el estado actual de ASP.NET WebAPI. Ahora se llama a la interfaz
IActionResult
y la implementación no ha cambiado mucho:fuente
Para aquellos errores en los que modelstate.isvalid es falso, generalmente envío el error cuando lo arroja el código. Es fácil de entender para el desarrollador que está consumiendo mi servicio. En general, envío el resultado usando el código a continuación.
Esto envía el error al cliente en el siguiente formato, que es básicamente una lista de errores:
fuente