Antecedentes
Estoy desarrollando una capa de servicio API para un cliente y se me ha pedido que capture y registre todos los errores a nivel mundial.
Entonces, mientras que algo como un punto final desconocido (o acción) se maneja fácilmente usando ELMAH o agregando algo como esto a Global.asax
:
protected void Application_Error()
{
Exception unhandledException = Server.GetLastError();
//do more stuff
}
. . Los errores no controlados que no están relacionados con el enrutamiento no se registran. Por ejemplo:
public class ReportController : ApiController
{
public int test()
{
var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
return foo;
}
}
También he intentado establecer el [HandleError]
atributo globalmente al registrar este filtro:
filters.Add(new HandleErrorAttribute());
Pero eso tampoco registra todos los errores.
Problema / Pregunta
¿Cómo intercepto errores como el generado al llamar /test
arriba para poder registrarlos? Parece que esta respuesta debería ser obvia, pero he intentado todo lo que puedo pensar hasta ahora.
Idealmente, quiero agregar algunas cosas al registro de errores, como la dirección IP del usuario solicitante, la fecha, la hora, etc. También quiero poder enviar un correo electrónico al personal de soporte automáticamente cuando se encuentre un error. ¡Todo esto lo puedo hacer si solo puedo interceptar estos errores cuando ocurren!
¡RESUELTO!
Gracias a Darin Dimitrov, cuya respuesta acepté, me di cuenta de esto. WebAPI no maneja los errores de la misma manera que un controlador MVC normal.
Esto es lo que funcionó:
1) Agregue un filtro personalizado a su espacio de nombres:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BusinessException)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
ReasonPhrase = "Exception"
});
}
//Log Critical errors
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred, please try again or contact the administrator."),
ReasonPhrase = "Critical Exception"
});
}
}
2) Ahora registre el filtro globalmente en la clase WebApiConfig :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
config.Filters.Add(new ExceptionHandlingAttribute());
}
}
O puede omitir el registro y simplemente decorar un solo controlador con el [ExceptionHandling]
atributo.