Подтвердить что ты не робот

Легкий способ уловить все необработанные исключения в С#.NET.

У меня есть сайт, построенный на С#.NET, который имеет тенденцию создавать довольно устойчивый поток тайм-аутов SQL из различных пользовательских элементов управления, и я хочу легко поместить какой-то код, чтобы поймать все необработанные исключения и отправить их тому, что может их зарегистрировать и отобразить дружественное сообщение пользователю.

Как я, с минимальными усилиями, поймаю все необработанные исключения?

этот вопрос кажется невозможным, но для меня это не имеет смысла (и об .NET 1.1 в приложениях Windows):

4b9b3361

Ответ 1

Все необработанные исключения, наконец, прошли через Application_Error в global.asax. Таким образом, чтобы дать общее сообщение об исключении или выполнить операции регистрации, см. Application_Error.

Ответ 2

Если вам нужно поймать исключения во всех потоках, лучшим aproach является реализация UnhandledExceptionModule и добавление его в ваше приложение, посмотрите здесь  для примера

Ответ 3

Используйте метод Application_Error в файле Global.asax. Внутри реализации метода Application_Error вызовите Server.GetLastError(), запишите сведения об исключении, возвращенном Server.GetLastError(), но вы хотите.

например.

void Application_Error(object sender, EventArgs e) 
{ 
    // Code that runs when an unhandled error occurs
    log4net.ILog log = log4net.LogManager.GetLogger(typeof(object));
    using (log4net.NDC.Push(this.User.Identity.Name))
    {
        log.Fatal("Unhandled Exception", Server.GetLastError());
    }
}

Не уделяйте слишком много внимания материалам log4net, Server.GetLastError() является самым полезным битом, записывайте данные, но вы предпочитаете.

Ответ 4

Проект проекта ELMAH стоит попробовать, его список функций включает в себя:

ELMAH (модули регистрации ошибок и Handlers) является общесистемной ошибкой объект регистрации, который полностью подключаемый. Он может быть динамически добавлен к запущенному веб-приложению ASP.NET, или даже всех веб-приложений ASP.NET на машине, без каких-либо повторная компиляция или повторное развертывание.

  • Регистрация почти всех необработанных исключений.
  • Веб-страница для удаленного просмотра всего журнала перекодированных исключений.
  • Веб-страница для удаленного просмотра полной информации о любом зарегистрированном исключение.
  • Во многих случаях вы можете просмотреть оригинальный желтый экран смерти, который ASP.NET, сгенерированный для заданного исключение, даже в режиме customErrors выключен.
  • Уведомление по электронной почте о каждой ошибке в момент ее возникновения.
  • RSS-канал последних 15 ошибок из журнала.
  • Ряд реализаций хранилища для журнала

Подробнее об использовании ELMAH из dotnetslackers

Ответ 5

Вы можете подписаться на событие AppDomain.CurrentDomain.UnhandledException.

Ответ 6

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

Ответ 7

Вы имеете в виду обращение с ним во всех потоках, в том числе и с помощью стороннего кода? Внутри "известных" потоков просто ловите Exception в верхней части стека.

Ответ 8

Я бы рекомендовал посмотреть log4net и посмотреть, подходит ли это для части ведения журнала вопроса.

Ответ 9

При использовании .net 2.0 framework я использую встроенные службы мониторинга работоспособности. Здесь есть хорошая статья, описывающая этот метод: http://aspnet.4guysfromrolla.com/articles/031407-1.aspx

Если вы застряли с фреймворком 1.0, я бы использовал ELMAH: http://msdn.microsoft.com/en-us/library/aa479332.aspx

надеюсь, что это поможет

Ответ 10

Есть две части для обработки и идентификации этой проблемы.

Определение

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

Работа

Для обработки вы можете a) добавить HttpModeule. Видеть http://www.eggheadcafe.com/articles/20060305.asp Я бы предложил этот подход только в том случае, если нет абсолютно никакого контекста informaatn, и может быть выпущено IIS/aspnet, Короче говоря, для катастрофических ситуаций

b) Создайте абстрактный класс, называемый AbstractBasePage, который происходит из класса Page и имеет все ваши классы codebehind, полученные из AbstractBasePage

The AbstractBasePage может реализовать этот делегат Page.Error, чтобы все исключения, которые просачивались через n-ярусную архитектуру, могли быть пойманы здесь (и, возможно, зарегистрированы)

Я бы предложил эту причину для тех исключений, о которых вы говорите (SQlException), достаточно информации контекста, чтобы определить, что это таймаут и принять возможные меры. Это действие может включать перенаправление пользователя на страницу пользовательских ошибок с соответствующим сообщением для каждого отдельного исключения (Sql, webservice, тайм-ауты асинхронного вызова и т.д.).

Спасибо RVZ

Ответ 11

Ошибки таймаута обычно возникают, если вы не принудительно закрываете свои sqlconnections.

поэтому, если у вас есть

try {
    conn.Open();
    cmd.ExecuteReader();
    conn.Close();
} catch (SqlException ex) {
    //do whatever
}

Если что-то пойдет не так с этим ExecuteReader, ваше соединение не будет закрыто. Всегда добавляйте блок finally.

try {
    conn.Open();
    cmd.ExecuteReader();
    conn.Close();
} catch (SqlException ex) {
    //do whatever
} finally {
    if(conn.State != ConnectionState.Closed)
       conn.Close();
}

Ответ 12

Один короткий ответ - использовать (анонимные) методы делегата с общим кодом обработки при вызове делегата.

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

Тематическое исследование: точка боли - это веб-формы и сохранение данных в базе данных. У нас есть элемент управления, который отображает сохраненный статус для пользователя, и мы хотели иметь общий код обработки ошибок, а также общий дисплей без копирования-повторного использования на каждой странице. Кроме того, каждая страница делала это самостоятельно, поэтому единственной действительно общей частью кода была обработка и отображение ошибок.

Теперь, прежде чем захлопнуться, это не замена уровня доступа к данным и кода доступа к данным. Все, что все еще предполагалось, существует, хорошее разделение n-уровня и т.д. Этот код является UI-слоем, который позволяет нам писать чистый код пользовательского интерфейса, а не повторяться. Мы очень верим в исключения, но не исключаем, что некоторые исключения не требуют, чтобы пользователь получал общую страницу ошибок и терял работу. Там будут тайм-ауты sql, серверы идут вниз, взаимоблокировки и т.д.

Решение. То, как мы это делали, состояло в том, чтобы передать анонимный делегат методу в пользовательском элементе управления и по сути добавить блок try с помощью анонимных делегатов.

// normal form code.
private void Save()
{
    // you can do stuff before and after. normal scoping rules apply
    saveControl.InvokeSave(
        delegate
        {
            // everywhere the save control is used, this code is different
            // but the class of errors and the stage we are catching them at
            // is the same
            DataContext.SomeStoredProcedure();
            DataContext.SomeOtherStoredProcedure();
            DataContext.SubmitChanges();
        });
}

Сам метод SaveControl имеет такой метод, как:

public delegate void SaveControlDelegate();

public void InvokeSave(SaveControlDelegate saveControlDelegate)
{        
    // I've changed the code from our code. 
    // You'll have to make up your own logic.
    // this just gives an idea of common handling.
    retryButton.Visible = false;
    try
    {
        saveControlDelegate.Invoke();
    }
    catch (SqlTimeoutException ex)
    {
        // perform other logic here.
        statusLabel.Text = "The server took too long to respond.";
        retryButton.Visible = true;
        LogSqlTimeoutOnSave(ex);
    }
    // catch other exceptions as necessary. i.e.
    // detect deadlocks
    catch (Exception ex)
    {
        statusLabel.Text = "An unknown Error occurred";
        LogGenericExceptionOnSave(ex);
    }
    SetSavedStatus();
}

  • Существуют и другие способы достижения этого (например, общий базовый класс, intefaces), но в нашем случае это было лучше всего подходит.
  • Это не замена отличного инструмента, такого как Elmah для регистрации всех необработанных исключений. Это целенаправленный подход к обработке определенных исключений стандартным образом.

Ответ 13

Это старый вопрос, но лучший метод (для меня) здесь не указан. Итак, вот мы:

ExceptionFilterAttribute - это приятное и легкое решение для меня. Источник: http://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling.

public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var exception = context.Exception;
        if(exception is SqlTimeoutException)
        {
            //do some handling for this type of exception
        }
    }
}

И прикрепите его к f.e. HomeController:

[ExceptionHandling]
public class HomeController: Controller
{

}