Обработка необработанных исключений (C#)Processing Unhandled Exceptions (C#)

по Скотт Митчеллby Scott Mitchell

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

При возникновении ошибки времени выполнения для веб-приложения в рабочей среде важно уведомить разработчика и зарегистрировать ошибку, чтобы ее можно было диагностировать в более поздней момент времени.When a runtime error occurs on a web application in production it is important to notify a developer and to log the error so that it may be diagnosed at a later point in time. В этом учебнике содержатся общие сведения о том, как ASP.NET обрабатывает ошибки времени выполнения и просматривает один из способов выполнения пользовательского кода всякий раз, когда необработанное исключение передается в среду выполнения ASP.NET.This tutorial provides an overview of how ASP.NET processes runtime errors and looks at one way to have custom code execute whenever an unhandled exception bubbles up to the ASP.NET runtime.

ВведениеIntroduction

При возникновении необработанного исключения в приложении ASP.NET оно передается в среду выполнения ASP.NET, которая вызывает Error событие и отображает соответствующую страницу ошибки.When an unhandled exception occurs in an ASP.NET application, it bubbles up to the ASP.NET runtime, which raises the Error event and displays the appropriate error page. Существует три разных типа страниц ошибок: желтый экран "ошибка времени выполнения" (ИСОД); Сведения об исключении ИСОД; и пользовательские страницы ошибок.There are three different types of error pages: the Runtime Error Yellow Screen of Death (YSOD); the Exception Details YSOD; and custom error pages. В предыдущем учебном курсе мы настроили приложение на использование настраиваемой страницы ошибок для удаленных пользователей и сведений об исключении, исод для пользователей, посещенных локально.In the preceding tutorial we configured the application to use a custom error page for remote users and the Exception Details YSOD for users visiting locally.

Использование удобной для пользователя настраиваемой страницы ошибок, которая соответствует внешнему интерфейсу веб-узла, является предпочтительным для ошибки времени выполнения по умолчанию ИСОД, но отображение пользовательской страницы ошибки — лишь одна часть комплексного решения по обработке ошибок.Using a human-friendly custom error page that matches the look and feel of the site is preferred to the default Runtime Error YSOD, but displaying a custom error page is only one part of a comprehensive error handling solution. При возникновении ошибки в приложении в рабочей среде важно, чтобы разработчики получали извещение об ошибке, чтобы они могли неземлеть причину исключения и устранить ее.When an error occurs in an application in production, it is important that the developers are notified of the error so that they can unearth the cause of the exception and address it. Более того, сведения об ошибке необходимо регистрировать, чтобы можно было исследовать и диагностировать ошибку в более позднем моменте времени.Furthermore, the error's details should be logged so that the error can be examined and diagnosed at a later point in time.

В этом руководстве показано, как получить доступ к сведениям о необработанном исключении, чтобы они могли быть зарегистрированы и были уведомлены для разработчиков.This tutorial shows how to access the details of an unhandled exception so that they can be logged and a developer notified. В двух учебниках, которые следуют за этим одним из этих руководств, рассматриваются библиотеки регистрации ошибок, которые после установки ряда настроек автоматически уведомляют разработчиков об ошибках времени выполнения и записывает сведения о них.The two tutorials following this one explore error logging libraries that, after a bit of configuration, will automatically notify developers of runtime errors and log their details.

Note

Сведения, которые проверяются в этом учебнике, наиболее полезны, если необходимо обрабатывать необработанные исключения особым образом или индивидуально.The information examined in this tutorial is most useful if you need to process unhandled exceptions in some unique or customized manner. В случаях, когда требуется только регистрировать исключение и уведомлять разработчика, можно использовать библиотеку регистрации ошибок.In cases where you only need to log the exception and notify a developer, using an error logging library is the way to go. В следующих двух учебниках представлен обзор двух таких библиотек.The next two tutorials provide an overview of two such libraries.

Исполнение кода при Error возникновении событияExecuting Code When TheErrorEvent Is Raised

События предоставляют объекту механизм для сигнализации о том, что произошло нечто интересное, а другой объект — для выполнения кода в ответе.Events provide an object a mechanism for signaling that something interesting has occurred, and for another object to execute code in response. Как разработчик ASP.NET вы привыкли думать о событиях.As an ASP.NET developer you are accustomed to thinking in terms of events. Если вы хотите выполнить некоторый код, когда посетитель щелкнет определенную кнопку, создайте обработчик событий для этого Click события кнопки и вставьте в него код.If you want to run some code when the visitor clicks a particular Button, you create an event handler for that Button's Click event and put your code there. Учитывая, что среда выполнения ASP.NET создает свое Error событие всякий раз, когда возникает необработанное исключение, оно следует за тем, чтобы код для записи сведений об ошибке перейдет в обработчик событий.Given that the ASP.NET runtime raises its Error event whenever an unhandled exception occurs, it follows that the code for logging the error's details would go in an event handler. Но как создать обработчик событий для Error события?But how do you create an event handler for the Error event?

ErrorСобытие является одним из многих событий в HttpApplication классе , которые вызываются на определенных этапах конвейера HTTP в течение времени существования запроса.The Error event is one of many events in the HttpApplication class that are raised at certain stages in the HTTP pipeline during the lifetime of a request. Например, HttpApplication BeginRequest событие класса возникает в начале каждого запроса. его AuthenticateRequest событие возникает, когда модуль безопасности определил запрашивающего.For example, the HttpApplication class's BeginRequest event is raised at the start of every request; its AuthenticateRequest event is raised when a security module has identified the requestor. Эти HttpApplication события дают разработчику страницы возможность выполнять пользовательскую логику в различных точках времени существования запроса.These HttpApplication events give the page developer a means to execute custom logic at the various points in the lifetime of a request.

Обработчики событий для HttpApplication событий можно поместить в специальный файл с именем Global.asax .Event handlers for the HttpApplication events can be placed in a special file named Global.asax. Чтобы создать этот файл на веб-сайте, добавьте новый элемент в корневую папку веб-сайта, используя шаблон глобального класса приложений с именем Global.asax .To create this file in your website, add a new item to the root of your website using the Global Application Class template with the name Global.asax.

Рис. 1. добавление Global.asax в веб-приложениеFigure 1: Add Global.asax To Your Web Application
(Щелкните, чтобы просмотреть изображение с полным размером)(Click to view full-size image)

Содержимое и структура Global.asax файла, созданного Visual Studio, немного отличаются в зависимости от того, используется ли проект веб-приложения (WAP) или проект веб-сайта (WSP).The contents and structure of the Global.asax file created by Visual Studio differ slightly based on whether you are using a Web Application Project (WAP) or Web Site Project (WSP). С помощью WAP Global.asax реализуется как два отдельных файла — Global.asax и Global.asax.cs .With a WAP, the Global.asax is implemented as two separate files - Global.asax and Global.asax.cs. Global.asaxФайл не содержит ничего, кроме @Application директивы, ссылающейся на .cs файл; интересующие вас обработчики событий определяются в Global.asax.cs файле.The Global.asax file contains nothing but an @Application directive that references the .cs file; the event handlers of interest are defined in the Global.asax.cs file. Для ВСПС создается только один файл, Global.asax и обработчики событий определяются в <script runat="server"> блоке.For WSPs, only a single file is created, Global.asax, and the event handlers are defined in a <script runat="server"> block.

Global.asaxФайл, созданный в шаблоне глобального приложения Visual Studio в WAP, содержит обработчики событий с именами Application_BeginRequest , Application_AuthenticateRequest и Application_Error , которые являются обработчиками событий для HttpApplication событий BeginRequest , AuthenticateRequest и Error соответственно.The Global.asax file created in a WAP by Visual Studio's Global Application Class template includes event handlers named Application_BeginRequest, Application_AuthenticateRequest, and Application_Error, which are event handlers for the HttpApplication events BeginRequest, AuthenticateRequest, and Error, respectively. Существуют также обработчики событий с именами,, и, которые вызываются Application_Start Session_Start Application_End Session_End при запуске веб-приложения, при запуске нового сеанса, при завершении приложения и при завершении сеанса соответственно.There are also event handlers named Application_Start, Session_Start, Application_End, and Session_End, which are event handlers that fire when the web application starts, when a new session starts, when the application ends, and when a session ends, respectively. Global.asaxФайл, созданный в WSP с помощью Visual Studio, содержит только Application_Error Application_Start Session_Start Application_End обработчики событий,,, и Session_End .The Global.asax file created in a WSP by Visual Studio contains just the Application_Error, Application_Start, Session_Start, Application_End, and Session_End event handlers.

Note

При развертывании приложения ASP.NET необходимо скопировать Global.asax файл в рабочую среду.When deploying the ASP.NET application you need to copy the Global.asax file to the production environment. Global.asax.csФайл, созданный в WAP, не нужно копировать в рабочую среду, так как этот код компилируется в сборку проекта.The Global.asax.cs file, which is created in the WAP, does not need to be copied to production because this code is compiled into the project's assembly.

Обработчики событий, созданные с помощью шаблона глобального приложения Visual Studio, не являются исчерпывающими.The event handlers created by Visual Studio's Global Application Class template are not exhaustive. Можно добавить обработчик событий для любого HttpApplication события с помощью именования обработчика событий Application_EventName .You can add an event handler for any HttpApplication event by naming the event handler Application_EventName. Например, можно добавить в файл следующий код Global.asax для создания обработчика событий для AuthorizeRequest события:For example, you could add the following code to the Global.asax file to create an event handler for the AuthorizeRequest event:

protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
    // Event handler code
}

Аналогичным образом можно удалить все обработчики событий, созданные ненужным шаблоном глобального класса приложений.Likewise, you can remove any event handlers created by the Global Application Class template that are not needed. Для этого учебника требуется обработчик событий только для Error события. Удалите другие обработчики событий из Global.asax файла.For this tutorial we only require an event handler for the Error event; feel free to remove the other event handlers from the Global.asax file.

Note

Модули HTTP предлагают еще один способ определения обработчиков событий для HttpApplication событий.HTTP Modules offer another way to define event handlers for HttpApplication events. Модули HTTP создаются как файл класса, который можно разместить непосредственно в проекте веб-приложения или разделить в отдельную библиотеку классов.HTTP Modules are created as a class file that can be placed directly within the web application project or separated out into a separate class library. Так как они могут быть разделены на библиотеку классов, модули HTTP предлагают более гибкую и многократно используемую модель для создания HttpApplication обработчиков событий.Because they can be separated out into a class library, HTTP Modules offer a more flexible and reusable model for creating HttpApplication event handlers. В то время как Global.asax файл относится к веб-приложению, где он находится, модули HTTP могут быть скомпилированы в сборки, после чего Добавление модуля HTTP на веб-сайт выполняется так же просто, как удаление сборки в Bin папку и регистрация модуля в Web.config .Whereas the Global.asax file is specific to the web application where it resides, HTTP Modules can be compiled into assemblies, at which point adding the HTTP Module to a website is as simple as dropping the assembly in the Bin folder and registering the Module in Web.config. В этом учебнике не рассматривается создание и использование модулей HTTP, но две библиотеки регистрации ошибок, используемые в следующих двух учебниках, реализуются как модули HTTP.This tutorial does not look at creating and using HTTP Modules, but the two error logging libraries used in the following two tutorials are implemented as HTTP Modules. Дополнительные сведения о преимуществах модулей HTTP см. в статье Использование модулей и обработчиков HTTP для создания подключаемых компонентов ASP.NET.For more background on the benefits of HTTP Modules refer to Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components.

Получение сведений о необработанном исключенииRetrieving Information About the Unhandled Exception

На этом этапе у нас есть файл Global. asax с Application_Error обработчиком событий.At this point we have a Global.asax file with an Application_Error event handler. При выполнении этого обработчика событий необходимо уведомить разработчика об ошибке и записать сведения о нем.When this event handler executes we need to notify a developer of the error and log its details. Для выполнения этих задач сначала необходимо определить сведения о возникшем исключении.To accomplish these tasks we first need to determine the details of the exception that was raised. Используйте GetLastError метод объекта Server для получения сведений о необработанном исключении, которое привело Error к срабатыванию события.Use the Server object's GetLastError method to retrieve details of the unhandled exception that caused the Error event to fire.

protected void Application_Error(object sender, EventArgs e)
{
    // Get the error details
    HttpException lastErrorWrapper = 
        Server.GetLastError() as HttpException;
}

GetLastErrorМетод возвращает объект типа Exception , который является базовым типом для всех исключений в платформа .NET Framework.The GetLastError method returns an object of type Exception, which is the base type for all exceptions in the .NET Framework. Однако в приведенном выше коде объект исключения, возвращенный в объект, приводится к типу GetLastError HttpException .However, in the code above I am casting the Exception object returned by GetLastError into an HttpException object. Если событие запускается из Error -за возникновения исключения во время обработки ресурса ASP.NET, то созданное исключение упаковывается в HttpException .If the Error event is being fired because an exception was thrown during the processing of an ASP.NET resource then the exception that was thrown is wrapped within an HttpException. Чтобы получить фактическое исключение, причиной событие ошибки, используйте InnerException свойство.To get the actual exception that precipitated the Error event use the InnerException property. Если событие возникло Error из-за исключения на основе HTTP, например запроса к несуществующей странице, HttpException создается исключение, но не имеет внутреннего исключения.If the Error event was raised because of an HTTP-based exception, such as a request for a non-existent page, an HttpException is thrown, but it does not have an inner exception.

Следующий код использует GetLastErrormessage для получения сведений об исключении, вызвавшем Error событие, сохраняя HttpException в переменной с именем lastErrorWrapper .The following code uses the GetLastErrormessage to retrieve information about the exception that triggered the Error event, storing the HttpException in a variable named lastErrorWrapper. Затем он сохраняет тип, сообщение и трассировку стека исходного исключения в трех строковых переменных, проверяя, lastErrorWrapper является ли действительное исключение, вызвавшее Error событие (в случае с исключениями на основе HTTP) или просто оболочкой для исключения, созданного при обработке запроса.It then stores the type, message, and stack trace of the originating exception in three string variables, checking to see if the lastErrorWrapper is the actual exception that triggered the Error event (in the case of HTTP-based exceptions) or if it's merely a wrapper for an exception that was thrown while processing the request.

protected void Application_Error(object sender, EventArgs e)
{
    // Get the error details
    HttpException lastErrorWrapper = 
        Server.GetLastError() as HttpException;

    Exception lastError = lastErrorWrapper;
    if (lastErrorWrapper.InnerException != null)
        lastError = lastErrorWrapper.InnerException;

    string lastErrorTypeName = lastError.GetType().ToString();
    string lastErrorMessage = lastError.Message;
    string lastErrorStackTrace = lastError.StackTrace;
}

На этом этапе у вас есть вся информация, необходимая для написания кода, который будет записывать сведения об исключении в таблицу базы данных.At this point you have all the information you need to write code that will log the exception's details to a database table. Можно создать таблицу базы данных со столбцами для каждой из подробных сведений об ошибках — типа, сообщения, трассировки стека и т. д. Вместе с другими полезными сведениями, такими как URL-адрес запрашиваемой страницы и имя пользователя, выполнившего вход в систему.You could create a database table with columns for each of the error details of interest - the type, the message, the stack trace, and so on - along with other useful pieces of information, such as the URL of the requested page and the name of the currently logged on user. В Application_Error обработчике событий можно подключиться к базе данных и вставить в нее запись.In the Application_Error event handler you would then connect to the database and insert a record into the table. Аналогичным образом можно добавить код для оповещения разработчика об ошибке по электронной почте.Likewise, you could add code to alert a developer of the error via email.

Библиотеки регистрации ошибок, проверенные в следующих двух учебниках, обеспечивают такую функциональность, поэтому нет необходимости самостоятельно создавать журнал и уведомления об ошибках.The error logging libraries examined in the next two tutorials provide such functionality out of the box, so there's no need to build this error logging and notification yourself. Однако, чтобы продемонстрировать, что Error событие вызывается и что Application_Error обработчик событий может использоваться для регистрации сведений об ошибках и уведомления разработчика, добавим код, который уведомляет разработчика при возникновении ошибки.However, to illustrate that the Error event is being raised and that the Application_Error event handler can be used to log error details and notify a developer, let's add code that notifies a developer when an error occurs.

Уведомление разработчика при возникновении необработанного исключенияNotifying a Developer When an Unhandled Exception Occurs

При возникновении необработанного исключения в рабочей среде важно оповещать группу разработчиков о том, что они могут оценить ошибку и определить, какие действия необходимо предпринять.When an unhandled exception occurs in the production environment it is important to alert the development team so that they can assess the error and determine what actions need to be taken. Например, если при подключении к базе данных возникает ошибка, необходимо дважды проверить строку подключения и, возможно, открыть запрос в службу поддержки с вашей компанией для размещения в Интернете.For example, if there is an error in connecting to the database then you'll need to double check your connection string and, perhaps, open a support ticket with your web hosting company. Если исключение возникло из-за ошибки программирования, может потребоваться добавить дополнительный код или логику проверки, чтобы предотвратить возникновение таких ошибок в будущем.If the exception occurred because of a programming error, additional code or validation logic may need to be added to prevent such errors in the future.

Классы платформа .NET Framework в System.Net.Mail пространстве имен упрощают отправку сообщения электронной почты.The .NET Framework classes in the System.Net.Mail namespace make it easy to send an email. MailMessage Класс представляет сообщение электронной почты и имеет такие свойства To , как, From ,, Subject Body и Attachments .The MailMessage class represents an email message and has properties like To, From, Subject, Body, and Attachments. SmtpClassОбъект используется для отправки MailMessage объекта с помощью указанного SMTP-сервера; параметры SMTP-сервера можно указать программно или декларативно в <system.net> элементе в Web.config file .The SmtpClass is used to send a MailMessage object using a specified SMTP server; the SMTP server settings can be specified programmatically or declaratively in the <system.net> element in the Web.config file. Дополнительные сведения об отправке сообщений электронной почты в приложении ASP.NET см. в статье Отправка электронной почты в ASP.NETи часто задаваемые вопросы о системе .NET. mail.For more information on sending email messages in an ASP.NET application check out my article, Sending Email in ASP.NET, and the System.Net.Mail FAQ.

Note

<system.net>Элемент содержит параметры SMTP-сервера, используемые SmtpClient классом при отправке сообщения электронной почты.The <system.net> element contains the SMTP server settings used by the SmtpClient class when sending an email. У компании, в которой размещен веб-узел, вероятно, есть SMTP-сервер, который можно использовать для отправки электронной почты из приложения.Your web hosting company likely has an SMTP server that you can use to send email from your application. Дополнительные сведения о параметрах SMTP-сервера, которые следует использовать в приложении, см. в разделе о поддержке веб-узла.Consult your web host's support section for information on the SMTP server settings you should use in your web application.

Добавьте следующий код в Application_Error обработчик событий, чтобы отправить разработчику сообщение электронной почты при возникновении ошибки:Add the following code to the Application_Error event handler to send a developer an email when an error occurs:

void Application_Error(object sender, EventArgs e)
{
    // Get the error details
    HttpException lastErrorWrapper = 
        Server.GetLastError() as HttpException;

    Exception lastError = lastErrorWrapper;
    if (lastErrorWrapper.InnerException != null)
        lastError = lastErrorWrapper.InnerException;

    string lastErrorTypeName = lastError.GetType().ToString();
    string lastErrorMessage = lastError.Message;
    string lastErrorStackTrace = lastError.StackTrace;

    const string ToAddress = "support@example.com";
    const string FromAddress = "support@example.com";
    const string Subject = "An Error Has Occurred!";
    
    // Create the MailMessage object
    MailMessage mm = new MailMessage(FromAddress, ToAddress);
    mm.Subject = Subject;
    mm.IsBodyHtml = true;
    mm.Priority = MailPriority.High;
    mm.Body = string.Format(@"
<html>
<body>
  <h1>An Error Has Occurred!</h1>
  <table cellpadding=""5"" cellspacing=""0"" border=""1"">
  <tr>
  <tdtext-align: right;font-weight: bold"">URL:</td>
  <td>{0}</td>
  </tr>
  <tr>
  <tdtext-align: right;font-weight: bold"">User:</td>
  <td>{1}</td>
  </tr>
  <tr>
  <tdtext-align: right;font-weight: bold"">Exception Type:</td>
  <td>{2}</td>
  </tr>
  <tr>
  <tdtext-align: right;font-weight: bold"">Message:</td>
  <td>{3}</td>
  </tr>
  <tr>
  <tdtext-align: right;font-weight: bold"">Stack Trace:</td>
  <td>{4}</td>
  </tr> 
  </table>
</body>
</html>",
        Request.RawUrl,
        User.Identity.Name,
        lastErrorTypeName,
        lastErrorMessage,
        lastErrorStackTrace.Replace(Environment.NewLine, "<br />"));

    // Attach the Yellow Screen of Death for this error   
    string YSODmarkup = lastErrorWrapper.GetHtmlErrorMessage();
    if (!string.IsNullOrEmpty(YSODmarkup))
    {
        Attachment YSOD = 
            Attachment.CreateAttachmentFromString(YSODmarkup, "YSOD.htm");
        mm.Attachments.Add(YSOD);
    }

    // Send the email
    SmtpClient smtp = new SmtpClient();
    smtp.Send(mm);
}

Хотя приведенный выше код довольно длинный, основная часть этого кода создает код HTML, который отображается в сообщении электронной почты, отправленном разработчику.While the above code is quite lengthy, the bulk of it creates the HTML that appears in the email sent to the developer. Код начинается с ссылки на объект, HttpException возвращаемый GetLastError методом ( lastErrorWrapper ).The code starts by referencing the HttpException returned by the GetLastError method (lastErrorWrapper). Фактическое исключение, вызванное запросом, извлекается с помощью lastErrorWrapper.InnerException и присваивается переменной lastError .The actual exception that was raised by the request is retrieved via lastErrorWrapper.InnerException and is assigned to the variable lastError. Сведения о типе, сообщении и трассировке стека извлекаются из lastError и хранятся в трех строковых переменных.The type, message, and stack trace information is retrieved from lastError and stored in three string variables.

Затем MailMessage создается объект с именем mm .Next, a MailMessage object named mm is created. Текст сообщения электронной почты форматируется в формате HTML и отображает URL-адрес запрашиваемой страницы, имя пользователя, выполнившего вход в систему, и сведения об исключении (тип, сообщение и трассировка стека).The email body is HTML formatted and displays the URL of the requested page, the name of the currently logged on user, and information about the exception (the type, message, and stack trace). Одно из замечательных особенностей HttpException класса состоит в том, что можно создать HTML-код, используемый для создания желтого экрана сведений об исключении (исод), вызвав метод жестмлеррормессаже.One of the cool things about the HttpException class is that you can generate the HTML used to create the Exception Details Yellow Screen of Death (YSOD) by calling the GetHtmlErrorMessage method. Этот метод используется здесь для получения сведений об исключении ИСОД разметки и ее добавления в сообщение электронной почты в качестве вложения.This method is used here to retrieve the Exception Details YSOD markup and add it to the email as an attachment. Одно слово с осторожностью: Если исключение, вызвавшее Error событие, было исключением на основе HTTP (например, запрос несуществующей страницы), GetHtmlErrorMessage метод возвратит значение null .One word of caution: if the exception that triggered the Error event was an HTTP-based exception (such as a request for a non-existent page) then the GetHtmlErrorMessage method will return null.

Последним шагом является отправка MailMessage .The final step is to send the MailMessage. Это делается путем создания нового SmtpClient метода и вызова его Send метода.This is done by creating a new SmtpClient method and calling its Send method.

Note

Перед использованием этого кода в веб-приложении необходимо изменить значения в ToAddress FromAddress константах и support@example.com на любой адрес электронной почты, на который будет отправлено электронное письмо с уведомлением об ошибке и откуда они берутся.Before using this code in your web application you'll want to change the values in the ToAddress and FromAddress constants from support@example.com to whatever email address the error notification email should be sent to and originate from. Кроме того, необходимо указать параметры SMTP-сервера в <system.net> разделе статьи Web.config .You'll also need to specify SMTP server settings in the <system.net> section in Web.config. Обратитесь к поставщику веб-узла, чтобы определить параметры SMTP-сервера для использования.Consult your web host provider to determine the SMTP server settings to use.

С помощью этого кода в любое время при наличии ошибки разработчик отправляет сообщение электронной почты с описанием ошибки и содержит ИСОД.With this code in place anytime there's an error the developer is sent an email message that summarizes the error and includes the YSOD. В предыдущем учебном курсе мы продемонстрировали ошибку во время выполнения, посетив жанр. aspx и передавая недопустимое ID значение через строку запроса, например Genre.aspx?ID=foo .In the preceding tutorial we demonstrated a runtime error by visiting Genre.aspx and passing in an invalid ID value through the querystring, like Genre.aspx?ID=foo. Посещение страницы с Global.asax файлом на месте дает те же возможности взаимодействия с пользователем, что и в предыдущем учебнике. в среде разработки вы по-прежнему увидите желтой экран сведений об исключении, а в рабочей среде появится страница настраиваемой ошибки.Visiting the page with the Global.asax file in place produces the same user experience as in the preceding tutorial - in the development environment you'll continue to see the Exception Details Yellow Screen of Death, while in the production environment you'll see the custom error page. В дополнение к этому существующему поведению, разработчику отправляется сообщение электронной почты.In addition to this existing behavior, the developer is sent an email.

На рис. 2 показано сообщение электронной почты, полученное при посещении Genre.aspx?ID=foo .Figure 2 shows the email received when visiting Genre.aspx?ID=foo. В тексте электронного письма суммируются сведения об исключении, а в YSOD.htm вложении отображается содержимое, отображаемое в сведениях об исключении исод (см. рис. 3).The email body summarizes the exception information, while the YSOD.htm attachment displays the content that is shown in the Exception Details YSOD (see Figure 3).

Рис. 2. разработчик отправил уведомление по электронной почте при наличии необработанного исключенияFigure 2: The Developer Is Sent An Email Notification Whenever There's An Unhandled Exception
(Щелкните, чтобы просмотреть изображение с полным размером)(Click to view full-size image)

Рис. 3. уведомление по электронной почте содержит сведения об исключении Исод в виде вложенияFigure 3: The Email Notification Includes the Exception Details YSOD As An Attachment
(Щелкните, чтобы просмотреть изображение с полным размером)(Click to view full-size image)

Что насчет использования пользовательской страницы ошибокWhat About Using the Custom Error Page?

В этом учебнике было показано, как использовать Global.asax и Application_Error обработчик событий для выполнения кода при возникновении необработанного исключения.This tutorial showed how to use Global.asax and the Application_Error event handler to execute code when an unhandled exception occurs. В частности, мы использовали этот обработчик событий для уведомления разработчика об ошибке; Мы можем расширить его, чтобы также регистрировать сведения об ошибке в базе данных.Specifically, we used this event handler to notify a developer of an error; we could extend it to also log the error details in a database. Наличие Application_Error обработчика событий не влияет на работу конечного пользователя.The presence of the Application_Error event handler does not affect the end user's experience. Они по-прежнему видят настроенную страницу ошибки, сведения об ошибке ИСОД, ошибку времени выполнения ИСОД или настраиваемую страницу ошибки.They still see the configured error page, be it the Error Details YSOD, the Runtime Error YSOD, or the custom error page.

Естественно определить, Global.asax требуется ли файл и Application_Error событие при использовании настраиваемой страницы ошибки.It's natural to wonder whether the Global.asax file and Application_Error event is necessary when using a custom error page. При возникновении ошибки пользователь отображается на странице настраиваемой ошибки, поэтому не удается разместить код для уведомления разработчика и записать сведения об ошибке в класс кода программной части настраиваемой страницы ошибки?When an error occurs the user is shown the custom error page so why can't we put the code to notify the developer and log the error details into the code-behind class of the custom error page? Хотя вы, безусловно, можете добавить код в класс кода программной части пользовательской страницы, у вас нет доступа к сведениям об исключении, вызвавшем Error событие, при использовании методики, рассмотренной в предыдущем руководстве.While you can certainly add code to the custom error page's code-behind class you do not have access to the details of the exception that triggered the Error event when using the technique we explored in the preceding tutorial. Вызов GetLastError метода из пользовательской страницы ошибок возвращает Nothing .Calling the GetLastError method from the custom error page returns Nothing.

Причина этого поведения заключается в том, что пользовательская страница ошибок достигается с помощью перенаправления.The reason for this behavior is because the custom error page is reached via a redirect. Когда необработанное исключение достигает среды выполнения ASP.NET, обработчик ASP.NET создает его Error событие (которое выполняет Application_Error обработчик событий), а затем перенаправляет пользователя на настраиваемую страницу ошибки, выдавая Response.Redirect(customErrorPageUrl) .When an unhandled exception reaches the ASP.NET runtime the ASP.NET engine raises its Error event (which executes the Application_Error event handler) and then redirects the user to the custom error page by issuing a Response.Redirect(customErrorPageUrl). Response.RedirectМетод отправляет клиенту ответ с кодом состояния HTTP 302, что дает возможность браузеру запрашивать новый URL-адрес, а именно настраиваемую страницу ошибки.The Response.Redirect method sends a response to the client with an HTTP 302 status code, instructing the browser to request a new URL, namely the custom error page. Затем браузер автоматически запрашивает эту новую страницу.The browser then automatically requests this new page. Вы можете указать, что пользовательская страница ошибки была запрошена отдельно от страницы, на которой возникла ошибка, поскольку адресная строка браузера изменится на URL-адрес пользовательской страницы ошибок (см. рис. 4).You can tell that the custom error page was requested separately from the page where the error originated because the browser's Address bar changes to the custom error page URL (see Figure 4).

Рис. 4. при возникновении ошибки браузер перенаправляется на URL-адрес настраиваемой страницы ошибокFigure 4: When an Error Occurs the Browser Gets Redirected to the Custom Error Page URL
(Щелкните, чтобы просмотреть изображение с полным размером)(Click to view full-size image)

Побочным результатом является то, что запрос, в котором произошло необработанное исключение, заканчивается, когда сервер отвечает на перенаправление HTTP 302.The net effect is that the request where the unhandled exception occurred ends when the server responds with the HTTP 302 redirect. Последующий запрос к пользовательской странице ошибок — это новый запрос. к этому моменту модуль ASP.NET отменил сведения об ошибке и, более того, не имеет способа связать необработанное исключение в предыдущем запросе с новым запросом для настраиваемой страницы ошибки.The subsequent request to the custom error page is a brand new request; by this point the ASP.NET engine has discarded the error information and, moreover, has no way to associate the unhandled exception in the previous request with the new request for the custom error page. Именно поэтому функция GetLastError возвращает null при вызове со страницы настраиваемой ошибки.This is why GetLastError returns null when called from the custom error page.

Тем не менее, пользовательская страница ошибок может быть выполнена во время того же запроса, что привело к ошибке.However, it is possible to have the custom error page executed during the same request that caused the error. Server.Transfer(url)Метод передает выполнение на указанный URL-адрес и обрабатывает его в рамках одного запроса.The Server.Transfer(url) method transfers execution to the specified URL and processes it within the same request. Код в Application_Error обработчике событий можно переместить в класс кода программной части пользовательской страницы ошибки, заменив его в Global.asax следующим кодом:You could move the code in the Application_Error event handler to the custom error page's code-behind class, replacing it in Global.asax with the following code:

protected void Application_Error(object sender, EventArgs e)
{
    // Transfer the user to the appropriate custom error page
    HttpException lastErrorWrapper = 
        Server.GetLastError() as HttpException;

    if (lastErrorWrapper.GetHttpCode() == 404)
    {
        Server.Transfer("~/ErrorPages/404.aspx");
    }
    else
    {
        Server.Transfer("~/ErrorPages/Oops.aspx");
    }
}

Теперь при возникновении необработанного исключения Application_Error обработчик событий передает управление соответствующей пользовательской странице ошибок на основе кода состояния HTTP.Now when an unhandled exception occurs the Application_Error event handler transfers control to the appropriate custom error page based on the HTTP status code. Так как управление было передано, пользовательская страница ошибки имеет доступ к необработанным сведениям об исключении через Server.GetLastError и может уведомлять разработчика об ошибке и записывать сведения о ней.Because control was transferred, the custom error page has access to the unhandled exception information via Server.GetLastError and can notify a developer of the error and log its details. Server.TransferВызов останавливает выполнение обработчика ASP.NET, перенаправляющего пользователя на настраиваемую страницу ошибки.The Server.Transfer call stops the ASP.NET engine from redirecting the user to the custom error page. Вместо этого содержимое страницы пользовательской ошибки возвращается в качестве ответа на страницу, вызвавшую ошибку.Instead, the custom error page's content is returned as the response to the page that generated the error.

СводкаSummary

При возникновении необработанного исключения в веб-приложении ASP.NET среда выполнения ASP.NET создает Error событие и отображает настроенную страницу ошибки.When an unhandled exception occurs in an ASP.NET web application the ASP.NET runtime raises the Error event and displays the configured error page. Мы можем уведомить разработчика об ошибке, записать сведения о ней или обработать ее другим способом, создав обработчик событий для события ошибки.We can notify the developer of the error, log its details, or process it in some other fashion, by creating an event handler for the Error event. Существует два способа создания обработчика событий для HttpApplication таких событий, как Error : в Global.asax файле или в модуле HTTP.There are two ways to create an event handler for HttpApplication events like Error: in the Global.asax file or from an HTTP Module. В этом учебнике было показано, как создать Error обработчик событий в Global.asax файле, который уведомляет разработчиков об ошибке с помощью сообщения электронной почты.This tutorial showed how to create an Error event handler in the Global.asax file that notifies developers of an error by means of an email message.

Создание Error обработчика событий полезно, если необходимо обрабатывать необработанные исключения в определенном уникальном или настраиваемом виде.Creating an Error event handler is useful if you need to process unhandled exceptions in some unique or customized manner. Тем не менее, создание собственного Error обработчика событий для регистрации исключения или уведомления разработчика не является самым эффективным способом, поскольку уже существуют бесплатные и удобные в использовании библиотеки регистрации ошибок, которые можно настроить в течение нескольких минут.However, creating your own Error event handler to log the exception or to notify a developer is not the most efficient use of your time as there already exist free and easy to use error logging libraries that can be setup in a matter of minutes. В следующих двух учебниках рассматриваются две такие библиотеки.The next two tutorials examine two such libraries.

Поздравляем с программированием!Happy Programming!

Дополнительные материалыFurther Reading

Дополнительные сведения о разделах, обсуждаемых в этом руководстве, см. в следующих ресурсах:For more information on the topics discussed in this tutorial, refer to the following resources: