Estoy usando ASP.NET Core para mi nuevo proyecto de API REST después de usar ASP.NET Web API durante muchos años. No veo ninguna buena manera de manejar las excepciones en ASP.NET Core Web API. Traté de implementar el filtro / atributo de manejo de excepciones:
public class ErrorHandlingFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
HandleExceptionAsync(context);
context.ExceptionHandled = true;
}
private static void HandleExceptionAsync(ExceptionContext context)
{
var exception = context.Exception;
if (exception is MyNotFoundException)
SetExceptionResult(context, exception, HttpStatusCode.NotFound);
else if (exception is MyUnauthorizedException)
SetExceptionResult(context, exception, HttpStatusCode.Unauthorized);
else if (exception is MyException)
SetExceptionResult(context, exception, HttpStatusCode.BadRequest);
else
SetExceptionResult(context, exception, HttpStatusCode.InternalServerError);
}
private static void SetExceptionResult(
ExceptionContext context,
Exception exception,
HttpStatusCode code)
{
context.Result = new JsonResult(new ApiResponse(exception))
{
StatusCode = (int)code
};
}
}
Y aquí está mi registro de filtro de inicio:
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizationFilter());
options.Filters.Add(new ErrorHandlingFilter());
});
El problema que estaba teniendo es que cuando ocurre una excepción en mi AuthorizationFilter
no está siendo manejado por ErrorHandlingFilter
. Esperaba que fuera atrapado allí al igual que funcionaba con la antigua API web ASP.NET.
Entonces, ¿cómo puedo detectar todas las excepciones de aplicación, así como cualquier excepción de los filtros de acción?
c#
exception
asp.net-core
Andrei
fuente
fuente
UseExceptionHandler
middleware?UseExceptionHandler
middlewareRespuestas:
Middleware de manejo de excepciones
Después de muchos experimentos con diferentes enfoques de manejo de excepciones, terminé usando middleware. Funcionó mejor para mi aplicación ASP.NET Core Web API. Maneja excepciones de aplicaciones, así como excepciones de filtros de acción y tengo control total sobre el manejo de excepciones y la respuesta HTTP. Aquí está mi excepción en el manejo de middleware:
Regístralo antes de MVC en
Startup
clase:Puede agregar seguimiento de pila, nombre de tipo de excepción, códigos de error o cualquier cosa que desee. Muy flexible. Aquí hay un ejemplo de respuesta de excepción:
Considere inyectar
IOptions<MvcJsonOptions>
en elInvoke
método para luego usarlo cuando serialice el objeto de respuesta para utilizar la configuración de serialización de ASP.NET MVCJsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)
para una mejor consistencia de serialización en todos los puntos finales.Enfoque 2
Hay otra API no obvia llamada
UseExceptionHandler
que funciona "bien" para escenarios simples:Esta no es una manera muy obvia pero fácil de configurar el manejo de excepciones. Sin embargo, todavía prefiero el enfoque de middleware sobre él, ya que obtengo más control con la capacidad de inyectar las dependencias necesarias.
fuente
app.UseMiddleware<ErrorHandlingMiddleware>();
a justo antesapp.UseStaticFiles();
. La excepción parece haberse captado correctamente ahora. Esto me lleva a creerapp.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();
Hacer algo de hacker interno de middleware mágico para que el middleware ordene correctamente.Lo último
Asp.Net Core
(al menos desde 2.2, probablemente antes) tiene un middleware incorporado que lo hace un poco más fácil en comparación con la implementación en la respuesta aceptada:Debería hacer más o menos lo mismo, solo un poco menos de código para escribir.
Importante: Recuerde agregarlo antes
UseMvc
(oUseRouting
en .Net Core 3) ya que el orden es importante.fuente
Su mejor opción es usar middleware para lograr el registro que está buscando. Desea colocar su registro de excepciones en un middleware y luego manejar sus páginas de error que se muestran al usuario en un middleware diferente. Eso permite la separación de la lógica y sigue el diseño que Microsoft ha presentado con los 2 componentes de middleware. Aquí hay un buen enlace a la documentación de Microsoft: Manejo de errores en ASP.Net Core
Para su ejemplo específico, es posible que desee utilizar una de las extensiones en el middleware StatusCodePage o enrollar la suya de esta manera .
Puede encontrar un ejemplo aquí para registrar excepciones: ExceptionHandlerMiddleware.cs
Si no le gusta esa implementación específica, también puede usar ELM Middleware , y aquí hay algunos ejemplos: Elm Exception Middleware
Si eso no funciona para sus necesidades, siempre puede rodar su propio componente de Middleware mirando sus implementaciones de ExceptionHandlerMiddleware y ElmMiddleware para comprender los conceptos para construir el suyo propio.
Es importante agregar el middleware de manejo de excepciones debajo del middleware StatusCodePages pero sobre todos los demás componentes de middleware. De esa forma, su middleware Exception capturará la excepción, la registrará y luego permitirá que la solicitud continúe con el middleware StatusCodePage, que mostrará la página de error amigable al usuario.
fuente
UseStatusCodePages
sea útil en implementaciones de servicios de API web. No hay vistas ni HTML, solo respuestas JSON ...La respuesta bien aceptada me ayudó mucho, pero quería pasar HttpStatusCode en mi middleware para administrar el código de estado de error en tiempo de ejecución.
De acuerdo con este enlace, tengo una idea para hacer lo mismo. Así que fusioné la respuesta de Andrei con esto. Entonces mi código final está abajo:
1. Clase base
2. Tipo de clase de excepción personalizada
3. Middleware de excepción personalizado
4. Método de extensión
5. Configure el método en startup.cs
Ahora mi método de inicio de sesión en el controlador de cuenta:
Arriba puede ver si no he encontrado al usuario y luego levantar la HttpStatusCodeException en la que he pasado el estado HttpStatusCode.NotFound y un mensaje personalizado
en el middleware
bloqueado se llamará que pasará el control a
.
Pero, ¿qué pasa si tengo un error de tiempo de ejecución antes? Para eso he usado el bloque try catch que arroja la excepción y será atrapado en el bloque catch (Exception exceptionObj) y pasaré el control a
método.
He usado una sola clase ErrorDetails para uniformidad.
fuente
startup.cs
devoid Configure(IapplicationBuilder app)
Me aparece un errorIApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware
. Y agregué la referencia, dondeCustomExceptionMiddleware.cs
está.Para configurar el comportamiento de manejo de excepciones por tipo de excepción, puede usar Middleware de paquetes NuGet:
ASP.NET Core 2.0
ASP.NET Core 2.1+
.Código de muestra:
fuente
En primer lugar, gracias a Andrei porque he basado mi solución en su ejemplo.
Incluyo el mío ya que es una muestra más completa y podría ahorrarle algo de tiempo a los lectores.
La limitación del enfoque de Andrei es que no maneja el registro, capturando variables de solicitud potencialmente útiles y negociación de contenido (siempre devolverá JSON sin importar lo que el cliente haya solicitado: XML / texto plano, etc.).
Mi enfoque es usar un ObjectResult que nos permite usar la funcionalidad integrada en MVC.
Este código también evita el almacenamiento en caché de la respuesta.
La respuesta de error se ha decorado de tal manera que el serializador XML puede serializarla.
fuente
Primero, configure ASP.NET Core 2
Startup
para volver a ejecutar en una página de error cualquier error del servidor web y cualquier excepción no controlada.A continuación, defina un tipo de excepción que le permitirá generar errores con códigos de estado HTTP.
Finalmente, en su controlador para la página de error, personalice la respuesta según el motivo del error y si la respuesta será vista directamente por un usuario final. Este código supone que todas las URL de API comienzan con
/api/
.ASP.NET Core registrará los detalles del error para que pueda depurarlos, por lo que un código de estado puede ser todo lo que desea proporcionar a un solicitante (potencialmente no confiable). Si desea mostrar más información, puede mejorar
HttpException
para proporcionarla. Para errores de API, puede colocar información de error codificada con JSON en el cuerpo del mensaje reemplazándolareturn StatusCode...
porreturn Json...
.fuente
use middleware o IExceptionHandlerPathFeature está bien. hay otra manera en eshop
crear un filtro de excepción y registrarlo
fuente