Handling Errors and Exceptions in ASP.NET

Waqas Anwar
11 April 2010
15385 Views

No matter how experience developer you are and how perfect code you write, sooner or later your code will be interrupted by a programming mistake, some invalid user input, wrong data or any other unexpected circumstances. No software can run free from error, and ASP.NET applications are no exception. In this tutorial, I will show you how you can do error handling in ASP.NET applications and how you can configure custom error pages with user friendly messages.

Errors can occur in a variety of situations in your ASP.NET web applications. Some of the most common errors include attempt to access an object which is not initialized or attempt to connect a file which does not exist and so on. When an error occurs in your code, .NET checks to see whether any error hander appears in the current scope. If there is no error handler available, the page processing aborted and depending on whether the request is from the local computer or a remote client, an error page is displayed in the browser. Following is a sample error page showing user that an attempt to divide by zero has been made on the page which caused an error.

ASP.NET Error Page
A rich ASP.NET error page

Although the above error page is quite useful for developer to diagnose the actual cause of the error but it is not the page you want your end users to see in any situation because it can not only annoy them but it can also make them feel that the application is unstable or poorly developed. If an ASP.NET application is carefully developed and configured, the above error page will never appear.

Exception Handling
 
Exception handling is a programming technique which is supported by most modern languages and that allows developers to react to problems that occur at run time due to factors outside their control. When an exception occurs in your ASP.NET application code, you can handle it in a number of ways. The most common approach is to use structured exception handling in which you can use try-catch code blocks around error-prone code to catch specific exceptions that you can deal with, such as System.IO.FileNotFoundException. Following is the typical structure of try-catch blocks.
try
{
   // Problematic code goes here (i.e. opening a file, connecting to a database).
}
catch
{
   // An error has been detected. You can deal with it here.
}
finally
{
   // Clean up code here, regardless of whether or not there is an error
}

The try statement normally contains the code which can cause errors in your application. Any exceptions occur in the try block can be caught automatically and the code in the catch block will be executed when the error is detected. Usually, the catch block is used to report the error to the user or log it for future reference. Following code snippet shows a typical example of try-catch code block.
try
{
   // Risky code to connect database goes here.
}
catch (SqlException ex)
{
   // Catches common problems like connection errors.
}

Structure exception handling is very flexible because it allows you catch multiple specific exceptions as shown below:
try
{
   // Risky code to connect database goes here.
}
catch (SqlException ex)
{
   // Catches common problems like connection errors.
}
catch (NullReferenceException ex)
{
   // Catches problems resulting from an uninitialized object.
}
catch (Exception ex)
{
   // Catches any other errors.
}

In .NET all exception classes are derived from the base Exception class so that last catch block in the above code snippet will catch any type of exception occur in the try block.

Handling Exceptions at Page Level

If you have so many exception handling code blocks in your page, you can consider using the page-level error handler to catch multiple specific exceptions that might happen anywhere on the page. To handle exceptions at a page level, override the OnError method in your page and call Server.GetLastError() method which will give you access to the exception that just occurred. The following code snippet shows the usage of OnError method:
protected override void OnError(EventArgs e)
{
   Exception ex = Server.GetLastError();

   if (ex.GetBaseException() is DivideByZeroException)
   {
      Response.Write("Divide By Zero Error Occurred!");
      Response.StatusCode = 200;
      Server.ClearError();
      Response.End();
   }
}

Handling Exceptions at Application Level

ASP.NET allows you to catch all the unhandled exceptions of your application in a centralized location in Global.asax file. The following code shows how you can implement this behavior using the Application_Error method in Global.asax file.
void Application_Error(object sender, EventArgs e)
{
   Exception ex = Server.GetLastError();
  
   if (ex.GetBaseException() is DivideByZeroException)
   {
      System.Diagnostics.Trace.WriteLine(ex.ToString());
      Server.ClearError();
   }
}

Error Pages
 
If you are creating ASP.NET applications from some time, you must become familiar with the rich error pages that are shown to describe unhandled errors in your web pages. These rich error pages are extremely useful for developers for diagnosing the problems in their code during the development as they contain a wealth of information. Sometime these pages also display the source code where the problem occurred with the error line highlighted. These pages also display the type of error and a detailed error message describing the problem. The sample of such rich error page is shown at the start of this tutorial above.

By default, this rich error page is shown only for local requests that are sent from the http://localhost domain. ASP.NET doesn’t show rich error pages for requests from other computers; rather they receive a generic error page shown below.


Generic Client Error Page
A generic ASP.NET error page

This generic page does not have any details about the type of error or the code as sharing this information with other users would be a security risk. This page includes a generic message explaining that an error has occurred and describing how to change the configuration settings. You can change the configuration of your web application so that all users see the rich ASP.NET error page or user friendly custom error page. To configure these settings, you need to add the section in the web.config file as shown below:
<configuration>
   <system.web>
      <customErrors mode="RemoteOnly" />
      …
   </system.web> …
</configuration>

The mode attribute value can be one of the following:

RemoteOnly: The local requests made from the current computer will get rich error pages with detailed error information including its type, stack trace and error messages. The remote users will see generic error page as shown n the above figure. This is default value for mode attribute.

Off: Both local and remote users will see rich error pages with detail information about the error including error type, stack trace and error messages. This setting is helpful during development but should not be used in a deployed ASP.NET application.

On: Generic error pages are shown to both local and remote users. This is secure option but it complicates debugging during development because the developer will not be able to see the stack trace or error messages.

When you are deploying an ASP.NET application on a production server, you should use either RemoteOnly or On value for the mode attribute. However you don’t want your end users to see either rich or generic error pages as they are not very useful for them. In such cases, you can implement custom error pages in your application. You can create a single generic error page and configure ASP.NET to use it by adding defaultRedirect attribute in section in web.config as shown below:

<configuration>
   <system.web>
      <customErrors mode="RemoteOnly" defaultRedirect="~/error.aspx" />
      …
   </system.web>
   …
</configuration>

Now, if there is any HTTP error or unhandled application error occurs in your application, the user will be forwarded to error.aspx page. Please keep in mind that if you will set the value of mode attribute to Off, the user will still see the ASP.NET error page instead of error.aspx. In scenarios where you have set the value of mode attribute to RemoteOnly, remote users will see error.aspx while the local users see the ASP.NET error page. Following figure is showing a user friendly error.aspx page which all web site users will see if there is any error in the application.

Custom Error Page

A custom user friendly error page


You can do even more fine tuning of your web application by targeting specific HTTP errors to different error pages. This technique is shown in the following code:
<configuration>
   <system.web>
      <customErrors mode="RemoteOnly" defaultRedirect="~/error.aspx">
         <error statusCode="403" redirect="403.aspx" />
         <error statusCode="404" redirect="404.aspx" />

      </customErrors>
   </system.web>
</configuration>

Sometimes, the difference between an ordinary website and a professional web application is how it deals with errors. In this tutorial, I tried to explain you different options available to you related to exception handling and error pages. ASP.NET is very powerful server side technology and it also offers tracing and logging facilities to developers. I will try my best to write another tutorial on tracing and logging soon so keep visiting my website in future.