asp.net mvc - practice - Mejores prácticas: formas de manejar errores y excepciones en los controladores de API web
web api exception handling best practice (2)
Debe evitar usar try / catch en la acción del controlador.
Hay muchas formas de manejar su problema. La solución más simple y limpia sería usar un ActionFilter
para manejar las excepciones, algo así como:
public class ExceptionAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred!"),
ReasonPhrase = "Deadly Exception"
});
}
}
Luego puedes decorar tu acción con [ExceptionAttribute]
. Por supuesto, puede ampliar eso para comportarse de manera diferente para diferentes tipos de excepciones: excepciones comerciales, excepciones de datos, excepciones IO, etc., y devolver diferentes códigos de estado y comentarios basados en eso también.
Te recomiendo que leas un excelente artículo de Fredrik Normen: "Manejo de excepciones de la API web ASP.NET" http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception- handling.aspx .
Proporciona una excelente visión general de las técnicas de manejo de excepciones para Web API.
Estoy trabajando en un proyecto y he confiado mucho en la API web para todas mis operaciones del lado del cliente, ya sea la actualización de detalles de la cuenta, nuevos detalles agregados, modificar todo lo que se ha hecho con ASP.NET Web Api y Backbone.js
Escena actual:
En el esquema actual de cosas, estoy devolviendo un valor booleano de mis controladores de API web, para indicar si la operación fue exitosa o no.
Ejemplo:
[ActionName("UpdateAccountDetails")]
public bool PostAccountDetails(SomeModel model)
{
bool updateStatus = _customService.UpdateAccountDetails(model);
return updateStatus;
}
entonces, después de hacer una llamada ajax a esta acción, verifico la respuesta para verdadero / falso y visualizo mensajes de error o de éxito.
Problema:
Ahora lo que sucedió fue que comencé a recibir excepciones en mi acción, y la acción siguió siendo falsa y se mostró el mensaje de error. Pero no pude encontrar por qué?
Entonces, me preguntaba si existe una estructura de respuesta API estándar que todos sigan.
Inicialmente, tuve esta idea para tener cada acción de la API web para devolver esta clase
public class OperationStatus
{
public bool Result { get; set; } // true/false
public string Status { get; set; } // success/failure/warning
public List<string> WarningMessages { get; set; }
public List<string> ErrorMessages { get; set; }
public string OtherDetails { get; set; }
}
Este cambio sería un cambio importante y consumiría tiempo y recursos, así que pensé que sería mejor tener una segunda / tercera / cuarta opinión al respecto.
Por favor, piensa en esto.
Actualización:
Con un poco de ayuda de Mark Jones , he venido con esto
[ActionName("UpdateAccountDetails")]
public HttpResponseMessage PostAccountDetails(SomeModel model)
{
bool updateStatus;
string errorMessage;
try{
updateStatus = _customService.UpdateAccountDetails(model);
if(updateStatus)
{
return Request.CreateResponse(HttpStatusCode.OK);
}
return Request.CreateResponse(HttpStatusCode.InternalServerError);
}
catch(Exception exception)
{
errorMessage = exception.Message;
return Request.CreateResponse(HttpStatusCode.InternalServerError, errorMessage);
}
return updateStatus;
}
¿Alguna idea sobre esto?
En lugar de devolver un HttpResponseMessage , mantendría las API iguales y lanzaría una HttpResponseException cuando atrape una excepción. Algo como esto:
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.InternalServerError)
{ ReasonPhrase = errorMessage });
De esta forma, no cambiará la definición de su API y también funcionará con sus acciones GET, donde puede devolver algún objeto que deba ser serializado. Si está utilizando el método JQuery ajax para enviar la solicitud, su manejador de errores detectará esto y podrá recuperar el mensaje de texto en el parámetro errorThrown y manejarlo en consecuencia.