<%@ Page %>

ASP.NET Global Exception Handling

The Problem

When a runtime error occurs in ASP.NET an exception is thrown. Exceptions offer a myriad of benefits over the classic ASP error-handling model, including object-based errors, the ability to catch errors by type, and the ease of implementing structured error handling. But there are instances in every application when exceptions are not caught, and the result is a dreaded sight for developers: the default ASP.NET error page.

Click on the image to enlarge

So this begs the question: How can you ensure that users see your custom error page instead of the default page shown above?

The Solution

You can accomplish this using a few well-placed lines of code in the Global.asax. If you're unfamiliar with the Global.asax, it contains subroutines that handle application-level and session events such as the start of the application (Application_Start), the start of user sessions (Session_Start), and several others. The handler of interest in this article is the Application_Error subroutine that runs when an exception makes its way past your application code. The process for handling these exceptions is as follows:
  • Create an ASP.NET page called error.aspx; this is your custom error page. We'll examine the code for it in a moment.
  • In the Global.asax code-behind catch the last exception thrown.
  • Pull out the InnerException from the exception caught above. This is necessary because when an unhandled exception occurs .NET wraps it in a new exception of type HttpUnhandledException.
  • Place a few key values in the Session for retrieval on the custom error page.
  • Clear the error from the server.
  • Redirect to the custom error page.

The Global.asax.vb code

The following listing shows the code necessary to achieve this:

Sub Application_Error
(ByVal sender As Object, ByVal e As EventArgs)

   ' set default values
   Session("ErrorMsg") = 
   "No error information was available"
   Session("ExceptionType") = String.Empty
   Session("PageErrorOccured") = _
   Session("StackTrace") = String.Empty

  ' 2. Catch the last exception thrown
  Dim lastError As Exception = Server.GetLastError()

  ' 3. Pull out the InnerException
  If (Not lastError Is Nothing) Then
      lastError = lastError.InnerException
      ' 4. Place a few key values in the session for 
      ' retrieval on the custom error page
      Session("ErrorMsg") = lastError.Message
      Session("ExceptionType") = lastError.GetType.ToString
      Session("StackTrace") = lastError.StackTrace
  End If
  ' 5. Clear the error from the server
  ' 6. Redirect to the custom error page
Catch ex As Exception
   ' if we end up here, 
   'error handling has thrown an error.
   ' do nothing - don't want to create an infinite loop
   Response.Write("We apologize, but an" & _
   " unrecoverable error has occurred. Please click the " & _
   " back button on your browser and try again.")
End Try

End Sub

Your Custom Error Page

The process to follow in your error page code-behind is:
  • Add an ASP.NET label and name it lblMessage.
  • Grab the exception information placed in the session in Global.asax.vb.
  • Clear the values from the session.
  • Display a generic error message to the user. We will even include a link back to the offending page.
  • Add specific error information as HTML comments for use during development. This code should be removed when the application is moved to the production.
In the error.aspx.vb Page_Load, place the following:
   If (Not IsPostBack) Then
   ' 2. Grab the exception information from the session
   Dim errorMsg As String = 
   Dim pageErrorOccured As String = 
   Dim exceptionType As String = 
   Dim stackTrace As String = 

   ' 3. Clear the values from the session
   Session("ErrorMsg") = Nothing
   Session("PageErrorOccured") = Nothing
   Session("ExceptionType") = Nothing
   Session("StackTrace") = Nothing

   ' 4. Display a generic error message to the user
   lblMessage.Text = "We're sorry, but an unhandled " & _
   "error has occurred.<br/><br/>"

   lblMessage.Text = 
   String.Format("{0}To try again, " & _
   "click <a href='{1}' class='linkgreen'>
   here</a>.<br/><br/>", _
   lblMessage.Text, pageErrorOccured)

  ' 5. Add specific error information as 
  'HTML comments for you
  ' to view during development. 
  'You could also log the error to 
  ' the Windows event log here.
  lblMessage.Text = lblMessage.Text & "<!--" & Chr(10) & _
  "Error Message: " & errorMsg & Chr(10) & _
  "Page Error Occurred: " & pageErrorOccured & Chr(10) & _
  "ExceptionType: " & exceptionType & Chr(10) & _
  "Stack Trace: " & stackTrace & Chr(10) & _

End If
Catch ex As Exception
  ' If an exception is thrown in the 
  ' above code output the message
  ' and stack trace to the screen
  lblMessage.Text = ex.Message & " " & ex.StackTrace
End Try

To test this code create a new web form called ThrowsAnException.aspx and modify the Page_Load as follows:
Private Sub Page_Load(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) 
 Handles MyBase.Load
 Throw New Exception("Something didn't work right.")
End Sub
Upon running ThrowsAnException.aspx you will see your custom error page with the generic message and the link back to the offending page. If you view the HTML source in your browser you will see your error message ("Something didn't work right") and a stack trace in the HTML comments.


It always reflects poorly on a developer's code when users encounter errors, but additional damage is done when they are faced with an indecipherable error message on a nasty error page. The techniques discussed in this article allow you to show the user an attractive error page no matter what type of error has occurred.

Rob Walling is a Microsoft Certified Professional in VB.NET Web Applications and has worked as a software developer for the past four years. His areas of expertise include ASP.NET, VB.NET, and web-based application design. Rob is the principal of the Los Angeles-based consulting firm The Numa Group.

Posted On : 14 September 2003

Tags : ASP.NET Configuration Administration