2008-11-17 3 views
29

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

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

this question, кажется, говорят, что это невозможно, но это не имеет смысла для меня (и это о .NET 1.1 в окнах приложений):

+3

Разве это не лечение симптомов, а не причина? то есть не следует ли вам рассматривать причину таймаутов SQL, запустив трассировку SQL Profiler на сервере базы данных? – 2008-11-17 14:58:14

+1

Я думаю, вам нужно уточнить, что вы подразумеваете под «поймать»: как в попытке ..catch, где вы можете обрабатывать исключение, или если вы просто хотите получить информацию о необработанном исключении, и запишите где/когда (например, ELMAH) – 2009-07-29 06:05:04

ответ

2

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

25

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

+10

рассмотрите первое предложение; «У меня есть сайт, построенный на C# .NET, который имеет тенденцию ...» – 2008-11-17 22:03:25

+3

Чтобы кто-то пытался понять, что говорит предыдущий комментарий, я предполагаю, что он отвечает на комментарий, который был удален. (Подсказка: посмотрите, кто написал ответ и кто написал комментарий.) – ispiro 2014-05-25 13:39:53

+0

Возможно, вам нужно установить `` в web.config. Без этой записи он не работал на сервере производства для меня. – ghord 2014-11-26 07:05:53

1

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

16

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

+0

Вопрос относится к приложениям Windows, а не к веб-приложениям. – RoadWarrior 2008-11-17 17:09:45

7

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

1

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

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

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

1

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

Определение

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

Handling

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

б) Создать абстрактный класс под названием AbstractBasePage, который является производным от класса Page и имеют все ваши классы codebehind из AbstractBasePage

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

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

Благодаря РВЗ

13

Используйте метод 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() является наиболее полезным немного, бревенчатый детали однако вы предпочитаете.

8

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

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

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

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

3

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

1

Ошибки таймаута обычно возникают, если вы не принудительно закрываете свои 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(); 
} 
1

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

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

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

Теперь, прежде чем захлопнуться, это не заменяет уровень доступа к данным и код доступа к данным. Это все еще предполагается, что существует, хорошее разделение n-уровня и т. Д. Этот код является специфичным для пользовательского интерфейса, что позволяет нам писать чистый код пользовательского интерфейса и не повторяться. Мы очень верим в исключения, но не исключаем, что некоторые исключения не требуют, чтобы пользователь получал общую страницу ошибок и терял работу. Там будет 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 для регистрации всех необработанных исключений. Это целенаправленный подход к обработке определенных исключений стандартным образом.
0

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

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 
{ 

} 
Смежные вопросы