Ошибки журнала, обработанные в try..catch с Elmah

Я пытаюсь войти в систему с исключениями Elmah, обрабатываемыми в блоках try...catch.

Я добавил глобальный фильтр ошибок обработчика на Global.axax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new ElmahHandledErrorLoggerFilter());
    filters.Add(new HandleErrorAttribute());
}

Это мой ElmahHandledErrorLoggerFilter:

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

Он будет записывать только Исключение, как в try{ ... }catch{ throw new Exception(); }. Но это не проблема, проблема в том, что у меня есть метод с try-catch, вызванный из кода уже внутри другого try-catch. В этом случае, хотя я положил throw new Exception() внутри catch внутреннего метода, он не регистрирует исключение, он возвращается к catch в первом методе без регистрации Исключения. Например:

public void MainMethod()
{
    try
    {
        SecondMethod();
    }
    catch
    {
       ....second method jump here.....
    }
}

public void SecondMethod()
{
    try
    {
        int a =0;
        int b =;
        int result = b/a;
    }
    catch
    {
        throw new Exception();
    }
}

Исключение, созданное SecondMethod, не регистрируется Elmah. Он возвращается к основному методу catch. Если основной метод catch также имеет код throw new Exception(), тогда он регистрирует исключение. Однако он будет регистрироваться с трассировкой стека, указывающей на MainMethod, а не на SecondMethod.

То, что я хотел, чтобы каждый раз, когда он достиг уловки, не пересоздавая новое исключение, Elmah регистрировал бы исключение. Это связано с тем, что у меня есть много блоков try-catch в моем приложении, и я хочу регистрировать эти исключения без ручного входа в каждый try-catch. Однако, если вы скажете мне, как я могу зарегистрировать исключение из SecondMethod, это будет нормально.

Ответ 1

Используете ли вы ASP MVC?

Фильтры будут выполняться только для необработанных исключений, исходящих из методов контроллера. (Свойство context.ExceptionHandled указывает вам, был ли он обработан другим фильтром, а не блоком try-catch). Поэтому, если вы проглотите исключения в блоках try-catch внутри своих методов, они не будут обрабатываться фильтрами ошибок.

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

Когда вы решите перебросить исключения, посмотрите этот вопрос SO. В основном вы можете перестроить исключение, сохраняя трассировку стека с помощью:

try
{
    //code
}
catch (Exception ex)
{
    //...some error handling code here... 
    //Otherwise why the try-catch at all?
    throw;
}

Вы можете сделать это в своем примере MainMethod, и журнал регистрации будет сохранять трассировку стека.