wake-up-neo.com

Globaler Handler für nicht behandelte Ausnahme für OWIN/Katana?

Wie kann ein globaler Exception-Catcher-Handler in einer Katana-Implementierung (OWIN) implementiert werden?

In einer selbst gehosteten OWIN/Katana-Implementierung, die als Azure-Cloud-Dienst (Arbeiterrolle) ausgeführt wird, habe ich diesen Code in eine Middleware eingefügt:

throw new Exception("pooo");

Dann habe ich diesen Code in die Start-Klasse-Konfigurationsmethode eingefügt und einen Haltepunkt im Ereignishandler festgelegt:

 AppDomain.CurrentDomain.UnhandledException += 
    CurrentDomain_UnhandledExceptionEventHandler;

und den Event-Handler in derselben Klasse (mit einem Haltepunkt in der ersten Zeile):

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);
}

Wenn der Code ausgeführt wird, wird der Haltepunkt nicht getroffen. Das Visual Studio Output-Fenster enthält jedoch Folgendes:

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

Ich habe auch versucht, das Wireup und den Handler auf die Worker Role OnStart-Methode zu verschieben, aber der Haltepunkt ist immer noch nicht erreicht.

Ich benutze keine WebAPI, habe aber Beiträge dazu gesehen, was dort gemacht wird, aber ich habe nichts klares gefunden, also hier.

Ausführung unter .NET Framework 4.5.2, VS 2013.

Alle Ideen geschätzt. Vielen Dank.

30
Snowy

Versuchen Sie, eine benutzerdefinierte Middleware zu schreiben und als first middleware zu platzieren:

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
      }
   }
 }

Platzieren Sie es als first middleware:

public class Startup
{
    public void Configuration(IAppBuilder builder)
    {
        var config = new HttpConfiguration();

        builder.Use<GlobalExceptionMiddleware>();
        //register other middlewares
    }
}

Wenn wir diese Middleware als erste Middleware registrieren, werden alle Ausnahmen, die in anderen Middlewares (im Stacktrace) auftreten, weiter verbreitet und vom try/catch-Block dieser Middleware erfasst.

Es ist nicht zwingend erforderlich, es immer als erste Middleware zu registrieren. Falls Sie für einige Middlewares keine globale Ausnahmebehandlung benötigen, registrieren Sie diese Middlewares einfach vor diesem.

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
    }
}
38
Khanh TO

Versuche dies:

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);
    }
}

Und beim Start:

public void Configuration(IAppBuilder app)
{
  var config = new HttpConfiguration();

  config.Services.Replace(typeof(IExceptionHandler), new CustomExceptionHandler());
}
1
Greg R Taylor

Ответ @Khanh TO отличный; Хороший краткий код, и хорошо объяснил.

Это не работает для меня. Weitere Informationen zu .NET MVC finden Sie unter:

throw new Exception("Test GlobalExceptionMiddleware");

Исключение не было перехвачено в методе Invoke.

:То очень легко отладить:

  1. Поместите точку останова в тестовое исключение.
  2. УдарF10или перебирайте каждую строку, пока не дойдете до кода, который is обрабатывает исключение.

Для меня был добавлен код к BaseController, переопределяющему OnException. Этот код обрабатывал исключение и не перебрасывал. Я надеюсь, что это полезное дополнение к ответу @Khanh TO.

Обновление

Хорошо, я понимаю, что этот вопрос помечен с помощью Web API, и мой вариант использования .NET MVC, но я нашел этот вопрос при поиске промежуточного программного обеспечения Owin. Когда я отлаживаю свое решение с тестовым исключением и наблюдаю $exception в представлении Lokale, исключение пропало, когда я возвращаюсь к промежуточному программному обеспечению Owin. Поэтому я не использовал код ответе @Khanh TO. Wenn Sie versuchen, in Startup und Global.asax zu fangen. Sie können OnException in den folgenden Kategorien auswählen:

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

Этот ответ будет перехватывать любые исключения прижения и любые исключения в коно. Этого достаточно для моих нужд.

0
Jess