web-dev-qa-db-fra.com

Gestionnaire global d'exception non gérée pour OWIN/Katana?

Quelle est la manière appropriée d'implémenter un gestionnaire d'attrape-gestionnaire d'exception global dans une implémentation Katana (OWIN)?

Dans une implémentation OWIN/Katana auto-hébergée s'exécutant en tant que service cloud Azure (rôle de travail), j'ai placé ce code dans un middleware:

throw new Exception("pooo");

Ensuite, j'ai placé ce code dans la méthode de configuration de la classe de démarrage, en définissant un point d'arrêt dans le gestionnaire d'événements:

 AppDomain.CurrentDomain.UnhandledException += 
    CurrentDomain_UnhandledExceptionEventHandler;

et le gestionnaire d'événements de la même classe (avec un point d'arrêt défini sur la première ligne):

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

Lorsque le code est exécuté, le point d'arrêt n'est pas touché. La fenêtre de sortie de Visual Studio inclut cependant ceci:

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

J'ai également essayé de déplacer le wireup et le gestionnaire vers la méthode OnStart du rôle du travailleur, mais le point d'arrêt n'est toujours pas atteint.

Je n’utilise pas du tout WebAPI, mais j’ai jeté un coup d’œil aux articles sur ce qui s’y fait, mais je n’ai rien trouvé de clair, alors je suis là.

Fonctionnant sur .NET Framework 4.5.2, VS 2013.

Toutes les idées appréciées. Merci.

30
Snowy

Essayez d’écrire un middleware personnalisé et de le placer comme middleware first:

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

Placez-le en tant que middleware first:

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

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

Lorsque nous enregistrons ce middleware en tant que premier milieu, toute exception se produisant dans d'autres middlewares (en bas de la pile) se propagera et sera interceptée par le bloc try/catch de ce middleware.

Il n'est pas obligatoire de toujours l'enregistrer en tant que premier middleware. Si vous n'avez pas besoin de la gestion globale des exceptions pour certains middlewares, il vous suffit d'enregistrer ces middlewares avant celui-ci.

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

Essaye ça:

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

Et au démarrage:

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

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

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

То не работает для меня. Добавил тестовое исклчение к одному из моих контроллеров .NET MVC, maintenant:

throw new Exception("Test GlobalExceptionMiddleware");

Cliquez ici pour en savoir plus sur Invokename__.

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

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

Для меня был добавлен код к BaseControllername__, переопредялему OnExceptionname__. Тот код обрабатывал исключение et 2 ans Cliquez ici pour en savoir plus sur les événements de @Khanh TO.

Обновление

Хорошо, я понимаю, что этот вопрос помечен с помощью API Web, и мой вариант использования .NET MVC, но я нашел этот вопрос при поиске промежуточного программного обеспечения Owin. Когда ÿ отлаживаю свое решение с тестовым исключением Ø наблюдаю $exception  представлении sections locales, исключение пропало , когда я возвращаюсь к промежуточному программному обеспечению Owin. Поэтому я не использовал код в ответе @Khanh TO. Cliquez ici pour afficher/télécharger/essayer par le démarrage (Startup) et Global.asax. Меня также есть OnExceptionв моем базовом контроллере, как то:

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

Vous êtes le premier à donner votre avis sur cet objet Того достаточно для моих нужд.

0
Jess