Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Просмотреть или скачать образец кода (описание загрузки)
Если ошибка среды выполнения возникает в веб-приложении в рабочей среде, важно уведомлять разработчика и регистрировать ошибку, чтобы она была диагностирована в последующий момент времени. В этом руководстве представлен обзор того, как ASP.NET обрабатывает ошибки среды выполнения, и рассматривается один из способов выполнения пользовательского кода всякий раз, когда необработанные исключения поступают в ASP.NET время выполнения.
Введение
Когда в приложении ASP.NET возникает необработанное исключение, оно доходит до среды выполнения ASP.NET, которая инициирует событие Error и отображает соответствующую страницу ошибки. Существует три различных типа страниц ошибок: Желтый экран смерти при ошибке выполнения (YSOD); YSOD с информацией об исключении; и настраиваемые страницы ошибок.
В предыдущем руководстве мы настроили приложение для использования пользовательской страницы ошибок для удаленных пользователей и YSOD с деталями исключений для пользователей, работающих локально.
Использование понятной пользовательской страницы ошибок, которая соответствует стилю и оформлению сайта, предпочтительнее стандартной ошибки YSOD, но отображение пользовательской страницы ошибок является лишь одной частью комплексной системы обработки ошибок. При возникновении ошибки в рабочей среде важно, чтобы разработчики уведомляли об ошибке, чтобы они могли раскопить причину исключения и устранить ее. Кроме того, сведения об ошибке должны быть записаны в журнал, чтобы ошибка была проверена и диагностирована в более позднюю точку времени.
В этом руководстве показано, как получить доступ к подробным сведениям об необработанных исключениях, чтобы они могли быть зарегистрированы и уведомлены разработчиком. В двух руководствах, приведенных в этом руководстве, рассматриваются библиотеки ведения журнала ошибок, которые после немного конфигурации автоматически уведомляют разработчиков об ошибках среды выполнения и регистрируют их сведения.
Примечание.
Сведения, рассмотренные в этом руководстве, наиболее полезны, если необходимо обрабатывать необработанные исключения в определенном уникальном или настраиваемом режиме. В случаях, когда нужно записать исключение и уведомить разработчика, использование библиотеки логирования ошибок является правильным подходом. В следующих двух руководствах представлен обзор двух таких библиотек.
Выполнение кода приErrorвызове события
События предоставляют объекту механизм для уведомления о том, что произошло что-то интересное, и позволяют другому объекту выполнить код в ответ. Как ASP.NET разработчик вы привыкли думать с точки зрения событий. Если вы хотите запустить код, когда посетитель нажимает определенную кнопку, создайте обработчик событий для этого события Button Click и поместите код туда. Учитывая, что среда выполнения ASP.NET вызывает событие Error всякий раз, когда возникает необработанное исключение, следует, что код для ведения журнала сведений об ошибке будет проходить в обработчике событий. Но как создать обработчик событий для Error события?
Это событие Error является одним из многих событий класса HttpApplication, которые вызываются на определенных этапах конвейера HTTP во время обработки запроса. Например, событие класса HttpApplicationBeginRequest вызывается в начале каждого запроса; его событие AuthenticateRequest возникает, когда модуль безопасности определил идентификатор запросчика. Эти HttpApplication события позволяют разработчику страницы выполнять пользовательскую логику в различных точках времени существования запроса.
Обработчики событий для HttpApplication можно поместить в специальный файл с именем Global.asax. Чтобы создать этот файл на веб-сайте, добавьте новый элемент в корень веб-сайта с помощью шаблона "Глобальный класс приложений" с именем Global.asax.
Рис. 1. Добавление Global.asax в веб-приложение
(Щелкните, чтобы просмотреть изображение полного размера)
Содержимое и структура файла, созданного Global.asax Visual Studio, немного отличаются в зависимости от того, используется ли проект веб-приложения (WAP) или проект веб-сайта (WSP). С WAP Global.asax реализуется как два отдельных файла — Global.asax и Global.asax.vb. Файл Global.asax содержит только директиву @Application, которая ссылается на файл .vb; интересующие обработчики событий определены в файле Global.asax.vb. Для WSPs создается только один файл, Global.asaxа обработчики событий определяются в блоке <script runat="server"> .
Файл Global.asax, созданный в шаблоне глобального класса приложений Visual Studio для WAP, включает обработчики событий с именами Application_BeginRequest, Application_AuthenticateRequest, а также Application_Error, которые являются обработчиками событий для событий HttpApplication: BeginRequest, AuthenticateRequest и Error, соответственно. Существуют также обработчики событий с именем Application_Start, Session_StartApplication_Endи Session_End, которые являются обработчиками событий, которые запускаются при запуске веб-приложения, когда запускается новый сеанс, когда приложение заканчивается, и когда сеанс заканчивается соответственно. Файл Global.asax, созданный в WSP Visual Studio, содержит только Application_Error, Application_Start, Session_Start, Application_End и Session_End обработчики событий.
Примечание.
При развертывании приложения ASP.NET необходимо скопировать Global.asax файл в рабочую среду. Файл Global.asax.vb , созданный в WAP, не требуется копировать в рабочую среду, так как этот код компилируется в сборку проекта.
Обработчики событий, созданные шаблоном глобального класса приложений Visual Studio, не являются исчерпывающими. Можно добавить обработчик событий для любого HttpApplication события, назвав обработчик Application_EventNameсобытий. Например, можно добавить следующий код Global.asax в файл для создания обработчика событий для AuthorizeRequest события:
Sub Application_AuthorizeRequest(ByVal sender As Object, ByVal e As EventArgs)
' Event handler code
End Sub
Аналогичным образом можно удалить любые обработчики событий, созданные шаблоном глобального класса приложений, которые не нужны. Для этого руководства требуется только обработчик событий для Error события. Вы можете удалить другие обработчики событий из Global.asax файла.
Примечание.
Модули HTTP предлагают другой способ определения обработчиков событий для HttpApplication событий. Модули HTTP создаются в виде файла класса, который можно поместить непосредственно в проект веб-приложения или разделить на отдельную библиотеку классов. Так как они могут быть разделены в библиотеку классов, модули HTTP предлагают более гибкую и повторно использованную модель для создания HttpApplication обработчиков событий.
Global.asax В то время как файл предназначен для веб-приложения, в котором он находится, модули HTTP можно скомпилировать в сборки, в то время как добавление модуля HTTP на веб-сайт так же просто, как удаление сборки в папке Bin и регистрация модуля в Web.config. В этом руководстве не рассматривается создание и использование модулей HTTP, но две библиотеки ведения журнала ошибок, используемые в следующих двух руководствах, реализуются как модули HTTP. Дополнительные сведения о преимуществах модулей HTTP см. в статье "Использование модулей HTTP и обработчиков для создания подключаемых ASP.NET компонентов".
Получение сведений об необработанных исключениях
На этом этапе у нас есть файл Global.asax с обработчиком Application_Error событий. Когда этот обработчик событий выполняется, необходимо уведомить разработчика об ошибке и записать сведения о нем. Для выполнения этих задач сначала необходимо определить сведения об исключении, которое возникло. Используйте метод GetLastError объекта Server для получения сведений о необработанном исключении, которое вызвало событие Error.
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Get the error details
Dim lastErrorWrapper As HttpException = _
CType(Server.GetLastError(), HttpException)
End Sub
Метод GetLastError возвращает объект типаException, который является базовым типом для всех исключений в платформа .NET Framework. Однако в приведенном выше коде я привожу объект Exception, возвращаемый GetLastError, в объект HttpException.
Error Если событие запускается, так как исключение было выброшено во время обработки ресурса ASP.NET, то исключение, которое было выброшено, будет обёрнуто в оболочкуHttpException. Чтобы получить фактическое исключение, которое вызвало событие InnerException Error, используйте свойство.
Error Если событие возникло из-за HTTP-исключения, например, запроса на несуществующую страницу, HttpException выбрасывается исключение, но не имеет внутреннего исключения.
Следующий код с использованием GetLastErrormessage извлекает информацию об исключении, вызвавшем событие Error, и сохраняет HttpException в переменной с именем lastErrorWrapper. Затем он сохраняет тип, сообщение и трассировку стека исходного исключения в трех строковых переменных, проверяя, является ли lastErrorWrapper тем самым исключением, которое активировало событие Error (в случае исключений на основе HTTP) или же если это всего лишь оболочка для исключения, вызванного при обработке запроса.
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Get the error details
Dim lastErrorWrapper As HttpException = _
CType(Server.GetLastError(), HttpException)
Dim lastError As Exception = lastErrorWrapper
If lastErrorWrapper.InnerException IsNot Nothing Then
lastError = lastErrorWrapper.InnerException
End If
Dim lastErrorTypeName As String = lastError.GetType().ToString()
Dim lastErrorMessage As String = lastError.Message
Dim lastErrorStackTrace As String = lastError.StackTrace
End Sub
На этом этапе у вас есть все сведения, необходимые для написания кода, который будет записывать сведения об исключении в таблицу базы данных. Вы можете создать таблицу базы данных, добавив столбцы для каждого из интересующих вас аспектов ошибки: типа, сообщения, стека вызовов и так далее, а также других полезных данных, таких как URL запрошенной страницы и имя пользователя, который в данный момент вошел в систему. В обработчике Application_Error событий необходимо подключиться к базе данных и вставить запись в таблицу. Аналогичным образом можно добавить код для оповещения разработчика об ошибке по электронной почте.
Библиотеки ведения журнала ошибок, рассмотренные в следующих двух руководствах, предоставляют такие функциональные возможности из коробки, поэтому вам не нужно разрабатывать это ведение журнала ошибок и уведомления самостоятельно. Тем не менее, чтобы продемонстрировать, что событие вызывается и что ErrorApplication_Error обработчик событий можно использовать для регистрации сведений об ошибках и уведомления разработчика, давайте добавим код, который уведомляет разработчика о возникновении ошибки.
Уведомление разработчика о возникновении необработанного исключения
Если необработанное исключение возникает в рабочей среде, важно предупредить группу разработчиков, чтобы они могли оценить ошибку и определить, какие действия необходимо предпринять. Например, если при подключении к базе данных возникает ошибка, необходимо дважды проверить строку подключения и, возможно, открыть заявку в службу поддержки у вашей компании веб-хостинга. Если исключение произошло из-за ошибки программирования, может потребоваться добавить дополнительный код или логику проверки, чтобы предотвратить такие ошибки в будущем.
Классы платформы .NET Framework в System.Net.Mail пространстве имен упрощают отправку сообщения электронной почты. Класс MailMessage представляет сообщение электронной почты и имеет такие свойства, как To, From, , SubjectBodyи Attachments.
SmtpClass используется для отправки объекта MailMessage с помощью указанного SMTP-сервера; параметры SMTP-сервера можно задать программно или декларативно в элементе <system.net> в Web.config file. Дополнительные сведения об отправке сообщений электронной почты в приложении ASP.NET см. в моей статье, отправке электронной почты с сайта веб-страницы ASP.NET и System.Net.Mail.
Примечание.
Элемент <system.net> содержит параметры SMTP-сервера, используемые классом SmtpClient при отправке сообщения электронной почты. У вашей компании веб-размещения, скорее всего, есть SMTP-сервер, который можно использовать для отправки электронной почты из приложения. Обратитесь к разделу поддержки веб-узла для получения сведений о параметрах SMTP-сервера, которые следует использовать в веб-приложении.
Добавьте следующий код в Application_Error обработчик событий, чтобы отправить разработчику сообщение электронной почты при возникновении ошибки:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Get the error details
Dim lastErrorWrapper As HttpException = _
CType(Server.GetLastError(), HttpException)
Dim lastError As Exception = lastErrorWrapper
If lastErrorWrapper.InnerException IsNot Nothing Then
lastError = lastErrorWrapper.InnerException
End If
Dim lastErrorTypeName As String = lastError.GetType().ToString()
Dim lastErrorMessage As String = lastError.Message
Dim lastErrorStackTrace As String = lastError.StackTrace
Const ToAddress As String = "support@example.com"
Const FromAddress As String = "support@example.com"
Const Subject As String = "An Error Has Occurred!"
' Create the MailMessage object
Dim mm As New MailMessage(FromAddress, ToAddress)
mm.Subject = Subject
mm.IsBodyHtml = True
mm.Priority = MailPriority.High
mm.Body = string.Format( _
"<html>" & vbCrLf & _
" <body>" & vbCrLf & _
" <h1>An Error Has Occurred!</h1>" & vbCrLf & _
" <table cellpadding=""5"" cellspacing=""0"" border=""1"">" & vbCrLf & _
" <tr>" & vbCrLf & _
" <tdtext-align: right;font-weight: bold"">URL:</td>" & vbCrLf & _
" <td>{0}</td>" & vbCrLf & _
" </tr>" & vbCrLf & _
" <tr>" & vbCrLf & _
" <tdtext-align: right;font-weight: bold"">User:</td>" & vbCrLf & _
" <td>{1}</td>" & vbCrLf & _
" </tr>" & vbCrLf & _
" <tr>" & vbCrLf & _
" <tdtext-align: right;font-weight: bold"">Exception Type:</td>" & vbCrLf & _
" <td>{2}</td>" & vbCrLf & _
" </tr>" & vbCrLf & _
" <tr>" & vbCrLf & _
" <tdtext-align: right;font-weight: bold"">Message:</td>" & vbCrLf & _
" <td>{3}</td>" & vbCrLf & _
" </tr>" & vbCrLf & _
" <tr>" & vbCrLf & _
" <tdtext-align: right;font-weight: bold"">Stack Trace:</td>" & vbCrLf & _
" <td>{4}</td>" & vbCrLf & _
" </tr> " & vbCrLf & _
" </table>" & vbCrLf & _
" </body>" & vbCrLf & _
"</html>", _
Request.RawUrl, _
User.Identity.Name, _
lastErrorTypeName, _
lastErrorMessage, _
lastErrorStackTrace.Replace(Environment.NewLine, "<br />"))
'Attach the Yellow Screen of Death for this error
Dim YSODmarkup As String = lastErrorWrapper.GetHtmlErrorMessage()
If Not String.IsNullOrEmpty(YSODmarkup) Then
Dim YSOD As Attachment = _
Attachment.CreateAttachmentFromString(YSODmarkup, "YSOD.htm")
mm.Attachments.Add(YSOD)
End If
' Send the email
Dim smtp As New SmtpClient()
smtp.Send(mm)
End Sub
Хотя приведенный выше код довольно длинен, основная часть этого кода создает HTML-код, который отображается в сообщении электронной почты, отправленном разработчику. Код начинается с ссылки на HttpException возвращаемый методом GetLastError (lastErrorWrapper). Фактическое исключение, вызываемое запросом, извлекается через lastErrorWrapper.InnerException переменную и назначается переменной lastError. Сведения о типе, сообщении и трассировке стека извлекаются из lastError и сохраняются в трех строковых переменных.
MailMessage Затем создается объект с именемmm. Текст электронной почты отформатирован в формате HTML и отображает URL-адрес запрошенной страницы, имя пользователя, вошедшего в систему, и сведения об исключении (тип, сообщение и трассировка стека). Одним из классных моментов класса HttpException это возможность создания HTML-кода, используемого для создания Экран смерти с желтыми деталями исключения (YSOD), вызывая метод GetHtmlErrorMessage. Этот метод используется здесь для получения разметки YSOD деталей исключения и добавления ее в электронное письмо в виде вложения. Одно слово предостережения: если исключение, вызвавшее Error событие, было исключением на основе HTTP (например, запросом на несуществующую страницу), GetHtmlErrorMessage метод вернет.null
Последний шаг — отправить MailMessage. Это делается путем создания нового SmtpClient метода и вызова его Send метода.
Примечание.
Прежде чем использовать этот код в веб-приложении, необходимо изменить значения в константах ToAddress и FromAddress с support@example.com на конкретные адреса электронной почты, куда должно отправляться уведомление об ошибке и откуда оно будет исходить. Кроме того, необходимо указать параметры SMTP-сервера в разделе <system.net> в Web.config. Обратитесь к поставщику веб-узла, чтобы определить используемые параметры SMTP-сервера.
При наличии этого кода всякий раз, когда происходит ошибка, разработчику отправляется сообщение электронной почты, в котором излагается ошибка и содержится YSOD. В предыдущем руководстве мы продемонстрировали ошибку среды выполнения, посещая Genre.aspx и передавая недопустимое ID значение через строку запросов, например Genre.aspx?ID=foo. При посещении страницы с Global.asax файлом создается тот же пользовательский опыт, что и в предыдущем руководстве. В среде разработки вы продолжаете видеть Желтый Экран Смерти Исключений, а в производственной среде вы увидите пользовательскую страницу ошибок. В дополнение к этому существующему поведению разработчик отправляет сообщение электронной почты.
На рисунке 2 показана электронная почта, полученная при посещении Genre.aspx?ID=foo. Текст сообщения электронной почты содержит информацию об исключении, а вложение YSOD.htm демонстрирует содержимое, отображаемое на странице YSOD с деталями исключения (см. рис. 3).
Рис. 2. Разработчик отправляет уведомление по электронной почте при возникновении необработанного исключения
(Щелкните, чтобы просмотреть изображение полного размера)
Рис. 3. Уведомление по электронной почте содержит сведения об исключении (YSOD) в виде вложения
(Щелкните, чтобы просмотреть изображение полного размера)
Как использовать пользовательскую страницу ошибок?
В этом руководстве показано, как использовать Global.asax и обработчик событий Application_Error для выполнения кода при возникновении необработанного исключения. В частности, мы использовали этот обработчик событий для уведомления разработчика об ошибке; Мы могли бы расширить его, чтобы также регистрировать сведения об ошибке в базе данных. Наличие обработчика событий не влияет на работу конечного Application_Error пользователя. Они по-прежнему видят настроенную страницу ошибки, будь то YSOD с деталями ошибки, YSOD с ошибкой времени выполнения или настраиваемая страница ошибки.
Неудивительно задаться вопросом, необходимы ли файл Global.asax и событие Application_Error при использовании пользовательской страницы ошибок. Когда возникает ошибка, пользователю показывается настраиваемая страница ошибок, поэтому почему мы не можем поместить код, чтобы уведомить разработчика и записать сведения об ошибке в класс кода за настраиваемой страницей ошибок? Хотя вы, безусловно, можете добавить код в класс кода пользовательской страницы ошибок, у вас нет доступа к сведениям об исключении, вызвавшее Error событие при использовании метода, который мы изучили в предыдущем руководстве. Вызов метода GetLastError из настраиваемой страницы ошибок возвращает Nothing.
Причина такого поведения в том, что пользовательская страница ошибок загружается через перенаправление. Когда необработанное исключение достигает среды выполнения ASP.NET, подсистема ASP.NET инициирует событие Error (которое исполняет обработчик Application_Error), а затем перенаправляет пользователя на пользовательскую страницу ошибок, выполняя команду Response.Redirect(customErrorPageUrl). Метод Response.Redirect отправляет клиенту ответ с кодом состояния HTTP 302, указав браузеру запрос нового URL-адреса, а именно настраиваемую страницу ошибок. Затем браузер автоматически запрашивает эту новую страницу. Можно определить, что пользовательская страница ошибки была запрошена отдельно от страницы, на которой возникла ошибка, так как адресная строка браузера изменяется на URL-адрес настраиваемой страницы ошибок (см. рис. 4).
Рис. 4: При возникновении ошибки браузер перенаправляется на URL-адрес настроенной страницы ошибок.
(Щелкните, чтобы просмотреть изображение полного размера)
Чистый эффект заключается в том, что запрос, в котором произошло необработанное исключение, заканчивается, когда сервер отвечает на перенаправление HTTP 302. Последующий запрос на пользовательскую страницу ошибок — это новый запрос; По этому моменту подсистема ASP.NET отбрасывает сведения об ошибке и, более того, не имеет способа связать необработанное исключение в предыдущем запросе с новым запросом для настраиваемой страницы ошибок. Поэтому null возвращается при вызове GetLastError из пользовательской страницы ошибок.
Однако можно задействовать пользовательскую страницу ошибок в рамках текущего запроса, вызвавшего ошибку. Метод Server.Transfer(url) передает выполнение указанному URL-адресу и обрабатывает его в одном запросе. Код в обработчике событий можно переместить в Application_Error класс кода пользовательской страницы ошибок, заменив его Global.asax следующим кодом:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Get the error details
Dim lastErrorWrapper As HttpException = _
CType(Server.GetLastError(), HttpException)
If lastErrorWrapper.GetHttpCode() = 404 Then
Server.Transfer("~/ErrorPages/404.aspx")
Else
Server.Transfer("~/ErrorPages/Oops.aspx")
End If
End Sub
Теперь, когда возникает необработанное исключение, обработчик событий Application_Error передает управление на соответствующую пользовательскую страницу ошибок в зависимости от кода состояния HTTP. Так как управление было передано, пользовательская страница ошибок имеет доступ к сведениям о необработанном исключении с помощью Server.GetLastError и может уведомить разработчика об ошибке и записать эту информацию. Вызов Server.Transfer останавливает движок ASP.NET от перенаправления пользователя на пользовательскую страницу ошибок. Вместо этого содержимое настраиваемой страницы ошибок возвращается в качестве ответа на страницу, которая вызвала ошибку.
Итоги
Если необработанное исключение возникает Error в веб-приложении ASP.NET, среда выполнения ASP.NET вызывает событие и отображает настроенную страницу ошибки. Мы можем уведомить разработчика об ошибке, записать сведения или обработать его другим способом, создав обработчик событий для события Error. Существует два способа создания обработчика для событий HttpApplication, таких как Error: в файле Global.asax или в модуле HTTP. В этом руководстве показано, как создать Error обработчик событий в Global.asax файле, который уведомляет разработчиков об ошибке с помощью сообщения электронной почты.
Создание обработчика Error событий полезно, если необходимо обрабатывать необработанные исключения в определенном уникальном или настраиваемом режиме. Однако создание собственного Error обработчика событий для регистрации исключения или уведомления разработчика не является самым эффективным использованием времени, так как уже существуют бесплатные и простые в использовании библиотеки ведения журнала ошибок, которые могут быть настроены в течение нескольких минут. В следующих двух руководствах рассматриваются две такие библиотеки.
Счастливое программирование!
Дополнительные материалы
Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:
- ASP.NET Общие сведения о модулях HTTP и обработчиках HTTP
- Корректное реагирование на необработанные исключения — обработка необработанных исключений
-
HttpApplicationКласс и объект приложения ASP.NET - Обработчики HTTP и модули HTTP в ASP.NET
- Отправка электронной почты в ASP.NET
-
Общие сведения о
Global.asaxфайле - Использование модулей HTTP и обработчиков для создания подключаемых компонентов ASP.NET
-
Работа с файлом ASP.NET
Global.asax -
Работа с
HttpApplicationэкземплярами