it-swarm.com.ru

Необработанный исключительный глобальный обработчик для OWIN/Katana?

Как правильно реализовать глобальный обработчик исключений в реализации Katana (OWIN)?

В собственной реализации OWIN/Katana, работающей в качестве облачной службы Azure (рабочая роль), я поместил этот код в промежуточное ПО:

throw new Exception("pooo");

Затем я поместил этот код в метод конфигурации класса Startup, установив точку останова в обработчике событий:

 AppDomain.CurrentDomain.UnhandledException += 
    CurrentDomain_UnhandledExceptionEventHandler;

и обработчик событий того же класса (с точкой останова, установленной в первой строке):

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

Когда код запускается, точка останова не срабатывает. Окно вывода Visual Studio действительно включает это однако:

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

Я также попытался переместить соединение и обработчик в метод OnStart Worker Role OnStart, но точка останова все еще не достигнута.

Я вообще не использую WebAPI, но просмотрел сообщения о том, что там делается, но ничего не нашел, так что я здесь.

Работает на .NET Framework 4.5.2, VS 2013.

Все идеи приветствуются. Спасибо.

30
Snowy

Попробуйте написать собственное промежуточное программное обеспечение и поместить его как first 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
      }
   }
 }

Поместите его как first middleware:

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

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

Когда мы регистрируем это промежуточное ПО в качестве первого промежуточного, любые исключения, возникающие в других промежуточных программах (по трассе стека), будут распространяться вверх и перехватываться блоком try/catch этого промежуточного ПО.

Не обязательно всегда регистрировать его как первое промежуточное ПО, если вам не нужна глобальная обработка исключений для некоторых промежуточных программ, просто зарегистрируйте эти промежуточные программы до этого.

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

Попробуй это:

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

И при запуске:

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

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

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

Это не работает для меня. .NET MVC, например, так:

throw new Exception("Test GlobalExceptionMiddleware");

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

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

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

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

Обновление

Хорошо, я понимаю, что этот вопрос помечен с помощью веб-API и моего варианта использования .NET MVC, но я нашел этот вопрос при поиске промежуточного программного обеспечения Owin. $exception в представлении Местные жители, исключая пропало , когда я возвращаюсь к промежуточному программному обеспечению Owin. @Khanh TO. Вместо этого я добавил блоки try/catch в мой Startup и 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;
}

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

0
Jess