Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Displaying Gentle Error Messages with ASP.NET

  Learn how to display gentler error messages when errors are encountered while developing ASP.NET applications. In this article, Stephen Walther shows you how you can modify the default ASP.NET error page so that it displays motivational sounds, messages, and pictures.
Stephen's Blog

Difficulty: Easy
Time Required: Less than 1 hour
Cost: Free
Software: Visual Web Developer 2005 Express Edition
Hardware:
Download: Download

I fly out to companies and teach workshops on building ASP.NET applications to developers new to the ASP.NET framework. Typically a developer starts out excited to learn something new. Unfortunately, a developer's first experience of the ASP.NET framework is often the error page -- the angry page with the yellow background and the red error message.

When a novice developer encounters their first error message, I try to be reassuring. I explain that errors are normal and good and that an ASP.NET developer will view the error page at least half a billion times while developing a project of any reasonable complexity. After all, the mark of a good development framework is that it throws a lot of errors at you. A framework that throws a lot of errors prevents you from doing something stupid and deploying a buggy application into production.

However, the question remains: why does the ASP.NET Framework seem so angry? Why the harsh yellow background and bold red error messages (see Figure 1)? Why can't the error page be more gentle? In other words, why can't the error page be more Myst than Halo?

Figure 1 -- Angry ASP.NET Error Page

This question brings us to the topic of this article. The nice thing about the ASP.NET Framework is that you can customize just about any aspect of the framework in any way that you want. This month's project is to build a friendlier, gentler ASP.NET error page. Our error page will use nurturing colors such as blues and grays instead of yellows and reds. Furthermore, our custom error page will randomly display different motivational messages and pictures and play different soothing background sounds.

The Visual Studio Installer file that accompanies this article includes a new VB.NET and C# Project Template named Friendly Errors. If you choose this template when creating a new project, the default error message page will be replaced with a custom error message page (see Figure 2).

Figure 2 -- Gentle ASP.NET Error Page

Handling Application Exceptions

I should admit up front that I thought that this would be an extremely easy project. The ASP.NET Framework enables you to easily create a custom error page by adding a <customErrors> section to your application's Web configuration (Web.config) file. For example, adding the following Web.config file to the root of your application causes a page named CustomError.aspx to be displayed when there is any error:

<configuration>

<system.web>

<customErrors mode="On" defaultRedirect="~/CustomError.aspx" />

</system.web>

</configuration>

Adding this configuration file to your application works great. Whenever there is an error, the user is redirected to the CustomError.aspx page automatically. You can display any message in this page that you want. For example, you can display the message “This site is currently undergoing scheduled maintenance”.

Unfortunately, however, there is no way in the CustomError.aspx page to get information about the error that caused the redirect to the CustomError.aspx page. You can display a message, but you cannot display detailed error information.

Therefore, in this project, I took another approach. Instead of using the <customErrors> section, I handled the Application Error event. This event is raised whenever there is any unhandled exception in an application. In other words, if any code within a page or a component raises an exception, and the code is not wrapped by a Try...Catch block, then the Application Error event is raised.

There are two ways that you can handle the Application Error event. You can handle the event in the Global.asax file or you can handle the event by creating a custom HTTP Module. I handled the Application Error event in a module named FriendlyErrorsModule. The code for the FriendlyErrorsModule is contained in Listing 1.

Listing 1 -- FriendlyErrorModule.cs

using System; 

using System.Web; 

using System.Web.Configuration; 

namespace Superexpert 

{ 

/// <summary> 

/// Handles all unhanlded exceptions in an application 

/// </summary> 

public class FriendlyErrorsModule : IHttpModule 

{ 

  public void Init(HttpApplication app) 

  { 

    app.Error += new EventHandler(app_Error); 

  } 

  /// <summary> 

  /// When debug mode is enabled, display 

  /// friendly error page 

  /// </summary> 

  void app_Error(object sender, EventArgs e) 

  { 

    HttpApplication app = (HttpApplication)sender; 

    HttpContext context = app.Context; 

    Exception error = context.Server.GetLastError().GetBaseException(); 

    context.Response.Clear(); 

    CompilationSection compilationConfig = (CompilationSection)WebConfigurationManager.GetWebApplicationSection("system.web/compilation"); 

    if (compilationConfig.Debug) 

      context.Server.Transfer("~/FriendlyErrors/Debug.aspx"); 

    else 

      context.Server.Transfer("~/FriendlyErrors/Public.aspx"); 

  } 

  public void Dispose() 

  { 

  } 

} 

} 


Listing 1 -- FriendlyErrorModule.vb

 

Imports System 

Imports System.Web 

Imports System.Web.Configuration 

Namespace Superexpert 

''' <summary> 

''' Handles all unhanlded exceptions in an application 

''' </summary> 

Public Class FriendlyErrorsModule 

Implements IHttpModule 

  Public Sub Init(ByVal app As HttpApplication) Implements IHttpModule.Init 

    AddHandler app.Error, AddressOf app_Error 

  End Sub 

  ''' <summary> 

  ''' When debug mode is enabled, display 

  ''' friendly error page 

  ''' </summary> 

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

    Dim app As HttpApplication = CType(sender, HttpApplication) 

    Dim context As HttpContext = app.Context 

    context.Response.Clear() 

    Dim compilationConfig As CompilationSection = CType(WebConfigurationManager.GetWebApplicationSection("system.web/compilation"), CompilationSection) 

    If (compilationConfig.Debug) Then 

      context.Server.Transfer("~/FriendlyErrors/Debug.aspx") 

    Else 

      context.Server.Transfer("~/FriendlyErrors/Public.aspx") 

    End If 

  End Sub 

  Public Sub Dispose() Implements IHttpModule.Dispose 

  End Sub 

End Class 

End Namespace 

The class in Listing 1 implements the IHttpModule interface. This interface has two methods that you must implement: Init() and Dispose(). In Listing 1, the Init() method is used to wire the Application Error event to a handler named app_Error.

The app_Error handler checks whether debugging is enabled in the Web.config file. If debugging is enabled, then the user is transferred to a page named Debug.aspx whenever there is an error. Otherwise, if debugging is not enabled, the user is transferred to a page named Public.aspx.

Creating a Custom Error Page

The last part of this project involved creating the error page itself. The custom error page is named Debug.aspx. This page does a number of different things.

First, the page displays detailed error information. To get detailed error information, you must create an instance of the System.Diagnostics.StackTrace class. You can take advantage of the StackTrace class to get the name of the page associated with the error as well as the source code that caused the error.

The Friendly Errors Project Template includes a class named FriendlyError. This class includes methods for retrieving detailed error information. the Debug.aspx page uses the FriendlyError class behind the scenes.

The Debug.aspx page also displays a random picture. You can modify the pictures that the Debug.aspx page displays by modifying the contents of the FriendlyErrors/Pictures folder. The Debug.aspx page randomly displays one picture from this folder.

You can add any pictures to this folder that you want. For example, you can add baby pictures and motivational pictures of your favorite foods or persons.

The Debug.aspx page also displays a random motivational message. You can modify the motivational messages displayed by the Debug.aspx page by modifying the FriendlyErrors/Messages/Messages.xml file. This XML file contains a list of <message> elements that contain each of the motivational messages.

Finally, the Debug.aspx page plays a background sound. The page uses the <object> tag so that the background sound will play correctly in both Microsoft Internet Explorer and Mozilla Firefox. You can customize the background sounds used by the Debug.aspx page by modifying the contents of the FriendlyErrors/Sounds folder. The Debug.aspx page randomly plays a sound from this folder.

Again, you can add any sound file to this folder that you please. By default, the folder contains soothing chime sounds. If you want, you could add drop other motivational sounds into this folder such as Homer Simpson saying Doh!

Testing the Custom Error Page

You'll see the custom error page, Debug.aspx, whenever there is any unhandled exception in your project. Don't worry, unless you are the perfect programmer, you'll see the Debug.aspx pretty quickly when developing an application when using the Friendly Errors Project Template.

If you insist on intentionally creating an error in your application, then you can use the page in Listing 2. Both the C# and VB.NET versions of this page cause an exception that causes the Debug.aspx page to be displayed.

Listing 2 -- BadPage.aspx (C#)

<%@ Page Language="C#" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<script runat="server"> 

void Page_Load() 

{ 

  int zero = 0; 

  Response.Write(1/zero); 

} 

</script> 

<html xmlns="http://www.w3.org/1999/xhtml" > 

<head runat="server"> 

<title>Bad Page</title> 

</head> 

<body> 

<form id="form1" runat="server"> 

<div> 

I am a bad page 

</div> 

</form> 

</body> 

</html> 

Listing 2 -- BadPage.aspx (VB.NET)

<%@ Page Language="VB" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<script runat="server"> 

Sub Page_Load() 

  Dim Blow 

  Blow.Up() 

End Sub 

</script> 

<html xmlns="http://www.w3.org/1999/xhtml" > 

<head runat="server"> 

<title>Bad Page</title> 

</head> 

<body> 

<form id="form1" runat="server"> 

<div> 

I am a bad page 

</div> 

</form> 

</body> 

</html> 

Conclusion

The purpose of this month's column is to demonstrate that you can customize just about any aspect of the ASP.NET Framework: including the default error page. If you are going to spend countless hours staring at one particular page (and I've spent an embarrassing number of hours of my life staring at the error page) then you might as well make the experience pleasant.

Tags:

Follow the Discussion

  • Kit WestKit West

    The gentle message is definitely nicer than the angry one, but if there's truly a fault in the site, I'd like to know about it as a developer, not show it to users. We display something generic like, "An error was encountered and logged, and the operation was canceled -- sorry for the inconvenience. Please contact IT if this causes an urgent problem. Thank you." I get the user id, date/time, stack trace, along with parameter values and other context info, from my database (more accessible than system log).

  • wenchingchuawenchingchua

    That is really interesting. Thanks for sharing Smiley I never think of having sounds than showing nice messages Tongue Out

  • Robert McLawsRobert McLaws

    This is really cool, but why not make it an item template, instead of a project template? If you've already got a project starting from the ASP.NET AJAX project, the download doesn't help much.

    But this is cool, thanks!

  • anushka K Rajasinghaanushka K Rajasingha

    That is really interesting. Thanks for sharing

  • Meenakshi DharMeenakshi Dhar

    The download link is not working.. Can anybody please tell me from where I can download this example...

  • Justas BirgiolasJustas Birgiolas

    If you don't want to install the templates, you can look at the individual files. Once you run the vsi file from the archive, on the first screen look for a blue "View files in Windows Explorer" link. This will let you see and modify the individual files.

  • CoulisCoulis

    Sorry for my English, but the link ...

    "http://channel9.msdn.com/Photos/ZippedFiles/269023_FriendlyErrors.zip"

    is bad.

    Please, give me the good link

    Think

  • Clint RutkasClint I'm a "developer"

    Try http://mschnlnine.vo.llnwd.net/d1/ch9/9/8/0/1/5/2/269023_FriendlyErrors.zip

  • Mark NongkhlawMark Nongkhlaw

    URL : http://www.codeproject.com/KB/aspnet/%20/ErrorHandlingASPNET.aspx

    Note the %20 I deliberately inserted in the URL. I got :

    Server Error in '/' Application.

    The resource cannot be found.

    Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

    Requested URL: /KB/aspnet/ /ErrorHandlingASPNET.aspx

    Question : How do I handle such types of errors to display me a friendlier page?

  • harisharis

    hi..

    i wanna ask something..

    what about if i only want to get the error message?

    regards,

    haris

  • AgustinAgustin

    Beautiful posting !

    There are issues that may arise, you may trap errors in requests other than pages.

    So, if your .NET engine is also handling images (such as the VS's Casini server does), you might be trapping requests even after the containing page was served.

    You should use a different pattern in that case, provided Server.Transfer won't work as expected.

    Hope this helps Smiley

    Drop me a line would you ? agustingarzon@yahoo.com

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.