Gracefully Responding to Unhandled Exceptions - Processing Unhandled ExceptionsBy Scott Mitchell
When an unhandled exception occurs in an ASP.NET application, the visitor is, by default, shown either a "Runtime Error" or exception details page (which of the two pages is displayed depends upon the website's configuration and whether the visitor has come through localhost). Ideally, such esoteric error pages are only shown to developers; regular users should, instead, see a custom, user-friendly error page. In last week's article, Displaying User-Friendly Error Pages, we examined the steps to configure an ASP.NET web application to display custom, user-friendly web pages in response to unhandled exceptions.
The technique discussed in last week's article, however, uses a
Response.Redirect() internally to redirect the
user to the custom error page in the event of an unhandled exception. By redirecting the user, the context of the request
is lost (since the redirect causes the browser to send a new request to the error page). Consequently, the custom, user-friendly
error page lacks the ability to garner information about the error that just occurred. Such information might be desired in
order to display a more informative error message.
When an unhandled exception bubbles up to the ASP.NET runtime, the application-level
Error event fires. By creating
an event handler for this event, we can access the error details, log the error, notify a developer, or send the user to
the custom error page using
Server.Transfer() (which will maintain the context and allow the custom error page
to access the details of the unhandled exception).
In this article we'll examine how to create an event handler for the
Error event and examine a free, open-source
component for logging error details. Read on to learn more!
HttpApplicationclass represents the methods, properties, and events common to all ASP.NET web applications. One event of this class is the
Errorevent, which is fired whenever an unhandled exception bubbles up to the ASP.NET runtime. For example, imagine that in an ASP.NET web page you have code that connects to a database and runs a
DELETEstatement. If the database is offline when the page is visited, a
SqlExceptionwill be thrown. If your code lacks any error handling logic, the exception will bubble up from your ASP.NET page's code-behind class to the ASP.NET runtime, at which point the
Errorevent will be raised.
When an unhandled exception occurs, we typically want to do two things:
- Display a custom, user-friendly message to the end user (see Displaying User-Friendly Error Pages)
- "Process" the error - this may involve logging the error so that it can be inspected later; notifying a developer of the error by sending her an email; attempting to "fix" the problem
Errorevent. The event handler can be created in
Global.asaxor handled through an HTTP Module. In the event handler, details of the unhandled exception can be retrieved using the
Server.GetLastError()method. Once the error's details have been retrieved, the information can be logged, a developer can be notified, or control can be passed to a custom, user-friendly error page.
Error Event Handler in
Global.asaxis an optional file you can add to your web application's root directory to handle application- and session-level events. To create an event handler for the application's
Errorevent, start by adding the
Global.asaxfile to your project. Right-click on the project in Solution Explorer and choose Add New Item and choose the Global Application Class item type from the dialog box (see the screenshot below).
This will create a dummy
Global.asax file with event handlers for the main application-level events -
End - as well as event handlers for the session-level events
Since we're only concerned with the
Error event, feel free to remove the other event handlers.
Error event handler, information about the exception that just occurred can be accessed by calling:
This returns an
Exception object that houses information about the error that bubbled up to the runtime, causing
Error event to fire in the first place. If the exception was caused from an ASP.NET page, the original exception
is wrapped inside an
HttpUnhandledException; the ASP.NET page-level exception can be accessed via the
property, as we'll see shortly.
Imagine when an unhandled exception occurs we want to email a developer with details of the exception and then redirect the user
to a custom error page, just like we examined in Displaying User-Friendly Error Pages. To accomplish this, we would configure
<customErrors> settings in
Web.config appropriately, and then add the following code to the
Error event handler in
Pay particular attention to the first few lines of the event handler. Here we access the exception that just occurred
HttpContext.Current.Server.GetLastError()) and dig down into its
InnerException property if needed.
Then, the exception details are emailed to a specified email address using code taken verbatim from a previous article
of mine, Sending Email in ASP.NET 2.0. (The
SMTP relay server details used by this code can be found in
Say that a user visits a data-driven page and there's a problem in connecting to the database. The user will see the configured error page; behind the scenes, however, a developer will receive an email with the exception details:
Transferring Control - Rather Than Redirecting - to the Custom Error Page
As examined in Displaying User-Friendly Error Pages, the
Web.configcan be configured to display custom, user-friendly error pages to visitors when an unhandled exception occurs. Unfortunately, the ASP.NET runtime redirects a user to the custom error page when an unhandled exception occurs. Specifically, the runtime calls
Response.Redirect(customErrorPageUrl), which sends an HTTP 302 status to the browser, causing it to make a request for the specified URL (customErrorPageUrl). Since the redirect is a new web request, it has no connection or association with the request that had the unhandled exception. Consequently, calling
Server.GetLastError()from the custom error page will return a null value.
Sometimes, however, we want to have information about the error in the custom error page. Perhaps the message displayed depends
on the error that occurred, or we want to show exception details to authenticated visitors who are in a particular role.
This can be achieved by calling
Server.Transfer(customErrorPageUrl) in the
Error event handler.
From the docs,
"terminates execution of the current page and begins execution of a new page using the specified URL path to the page."
In essence, execution of the current request is handed off to another page on the server. There's no expicit redirect message
sent back to the client - it all happens server-side.
Server.Transfer(), the context is maintained so the custom error page can retrieve information about the
unhandled exception using
Server.GetLastError(). From the browser's perspective, there's no change in context either.
That is, the browser's address bar will still show the URL of the web page that caused the unhandled exception, and not
The download available at the end of this article presents a more intelligent custom error page (
This error page inspects the exception details and bases its message on the type of exception that occurred.
Error Event with HTTP Modules
An HTTP Module is a managed component that can respond to events raised by the ASP.NET runtime. The event handler that responds to the
Errorevent can, alternatively, be located in an HTTP Module. The benefit of using an HTTP Module is that it provides a "pluggable" component that can be added to an existing ASP.NET application by simply dropping the HTTP Module assembly in the
/bindirectory and adding a line or two of configuration to the application's
Creating and configuring an HTTP Module for handling errors is beyond the scope of this article. Instead, let me heartily recommend a free, open-source library provided by Atif Aziz, called Error Logging Modules And Handlers, or ELMAH. ELMAH is composed of an HTTP Module for logging unhandled exceptions to a data store and an HTTP Handler for displaying exception details in a web page or RSS feed.
ELMAH can be downloaded from its Google Code page, http://code.google.com/p/elmah/. For a thorough discussion on setting up and installing ELMAH, check out Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components. Setting up ELMAH takes 60 seconds or so, and provides a detailed log of exceptions, rich notification to developers, and user-friendly web pages for viewing exception details online. Highly recommended!
The download available at the end of this article uses the ELMAH library to log errors to a SQL Server 2005 Express Edition database...
When an unhandled exception occurs in a web application, we typically want to ensure that the end user sees a custom, user-friendly error page, and that the details of the exception are "processed." Processing the exception can differ for each application, but typically involves logging the exception and notifying a developer. A previous article, Displaying User-Friendly Error Pages, examined how to display a custom error page. In this article we saw how to create an event handler for the application
Rather than create your own exception logging and notification system, consider trying ELMAH, a free, open-source library that includes an HTTP Module for logging unhandled exceptions and another optional one for sending an email with the exception's details.