visual studio latest full control c# asp.net-web-api exception-handling owin katana

c# - studio - Controlador global de excepción no controlada para OWIN/Katana



install package ajaxcontroltoolkit (3)

¿Cuál es la forma correcta de implementar un controlador de receptor de excepción global en una implementación de Katana (OWIN)?

En una implementación auto-alojada de OWIN / Katana que se ejecuta como Azure Cloud Service (función de trabajador), coloqué este código en un Middleware:

throw new Exception("pooo");

Luego coloqué este código en el método de configuración de la clase de inicio, estableciendo un punto de interrupción en el controlador de eventos:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledExceptionEventHandler;

y el controlador de eventos en la misma clase (con un punto de interrupción establecido en la primera línea):

private static void CurrentDomain_UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e) { var exception = (Exception)e.ExceptionObject; Trace.WriteLine(exception.Message); Trace.WriteLine(exception.StackTrace); Trace.WriteLine(exception.InnerException.Message); }

Cuando se ejecuta el código, el punto de corte no se golpea. La ventana Visual Studio Output incluye esto sin embargo:

A first chance exception of type ''System.Exception'' occurred in redacted.dll A first chance exception of type ''System.Exception'' occurred in mscorlib.dll

También traté de mover el cableado y el manejador al método OnLikeer de Roles Trabajadores, pero aún así no se golpea el punto de interrupción.

No estoy usando WebAPI en absoluto, pero miré publicaciones sobre lo que se hace allí, pero no encontré nada claro, así que aquí estoy.

Funcionando en .NET Framework 4.5.2, VS 2013.

Todas las ideas apreciadas. Gracias.


Intente escribir un middleware personalizado y colocarlo como el primer middleware:

public class GlobalExceptionMiddleware : OwinMiddleware { public GlobalExceptionMiddleware(OwinMiddleware next) : base(next) {} public override async Task Invoke(IOwinContext context) { try { await Next.Invoke(context); } catch(Exception ex) { // your handling logic } } }

Colóquelo como el primer middleware:

public class Startup { public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); builder.Use<GlobalExceptionMiddleware>(); //register other middlewares } }

Cuando registramos este middleware como el primer medio, cualquier excepción que ocurra en otros middlewares (en el stacktrace) se propagará y quedará atrapado por el bloque try/catch de este middleware.

No es obligatorio registrarlo siempre como el primer middleware, en caso de que no necesite el manejo de excepciones globales para algunos middlewares, simplemente registre estos middlewares antes de este.

public class Startup { public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); //register middlewares that don''t need global exception handling. builder.Use<GlobalExceptionMiddleware>(); //register other middlewares } }


La respuesta de @Khanh TO es excelente; Buen código de acceso rápido, y bien explicado.

No estaba funcionando para mí. Agregué una excepción de prueba a uno de mis controladores .NET MVC como este:

throw new Exception("Test GlobalExceptionMiddleware");

La excepción no se detectó en el método Invoke .

Esto es muy fácil de depurar:

  1. Ponga un punto de interrupción en la excepción de prueba.
  2. Presiona F10 o pasa sobre cada línea hasta llegar al código que maneja la excepción.

Para mí, se agregó un código a un BaseController OnException . Este código manejaba la excepción y no volvía a lanzar. Espero que este sea un apéndice útil a la respuesta de @Khanh TO.

Actualizar

OK, me doy cuenta de que esta pregunta está etiquetada con API web, y mi caso de uso es .NET MVC, pero encontré esta pregunta en una búsqueda de middleware de Owin. Cuando depuro mi solución con la excepción de prueba y observo $exception en la vista de Localidades, la excepción desaparece cuando regreso al middleware de Owin. Por lo tanto, no he usado el código en la respuesta de @Khanh TO. En su lugar, he agregado bloques try / catch a mi Startup y Global.asax. También tengo OnException en mi controlador base así:

protected override void OnException(ExceptionContext filterContext) { if (filterContext.ExceptionHandled) { return; } var e = filterContext.Exception; Log.Error("BaseController.OnException caught exception:", e); filterContext.ExceptionHandled = true; }

Esta respuesta detectará cualquier excepción en el inicio de la aplicación y cualquier excepción en un controlador. Eso es suficiente para mis necesidades.


Prueba esto:

public class CustomExceptionHandler : IExceptionHandler { public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) { // Perform some form of logging context.Result = new ResponseMessageResult(new HttpResponseMessage { Content = new StringContent("An unexpected error occurred"), StatusCode = HttpStatusCode.InternalServerError }); return Task.FromResult(0); } }

Y al inicio:

public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); config.Services.Replace(typeof(IExceptionHandler), new CustomExceptionHandler()); }