You want the event-handling methods described in this chapter to write detailed messages to an error log for use in debugging your application, but you want to display friendly, informative messages to the user.
Create a custom exception class that includes a property to hold the
user-friendly message, and then, when an error occurs, instantiate a
new exception object of the custom type in the
Catch
block of your error-handling code, set the
property of the exception to the desired message, and then throw the
new exception.
Use the .NET language of your choice to create the custom exception
class by deriving from System.ApplicationException
and adding a property to hold the user-friendly message, giving it a
name like userFriendlyMessage
.
In the code-behind for the ASP.NET pages of your application that need to perform error handling, use the .NET language of your choice to:
In the Catch
block of methods where informative
messages are useful, instantiate a new exception object of your
custom class type, set the userFriendlyMessage
property to the desired message, and then throw the new exception.
In the Application_Error
event handler, write the
detailed information provided by the exception object to the event
log and then display the message contained in the
userFriendlyMessage
property of the exception on a
common error message page.
The custom exception class we’ve created to
demonstrate this solution is shown in Example 7-10
(VB) and Example 7-11 (C#). The code showing how to
create the new exception is shown in Example 7-12
(VB) and Example 7-13 (C#). The code for the
Application_Error
event handler is shown in Example 7-14 (VB) and Example 7-15 (C#).
(Because the .aspx
file for this example
contains nothing related to the error handling, it is not included in
this recipe.)
The first step to providing user-friendly messages with your
exceptions is to create a new class that inherits from
System.ApplicationException
. (The
System.ApplicationException
class extends
System.Exception
but adds no new functionality. It
is meant to be used to differentiate between exceptions defined by
applications and those defined by the system.) You then need to add a
property to the class to support the user-friendly message. The last
step in creating the new exception class is to create a constructor
that will create the base exception, by calling the base class
constructor with the raw message and a reference to the inner
exception, and then set the user-friendly message. Example 7-10 (VB) and Example 7-11 (C#)
show how we have implemented these steps.
The new exception class is put to use in the Catch
block of your code by creating an instance of the new exception
class, passing it the original message, a reference to the exception,
and the desired user-friendly message. The reference to the original
exception is passed to preserve the linked list of exceptions. In
this case, your new exception will point to the original exception by
using the inner
property of the new exception.
After the new exception class is created, it is then thrown. Example 7-12 (VB) and Example 7-13 (C#)
illustrate a sample Catch
block.
As shown in Example 7-14 (VB) and Example 7-15 (C#), our sample
Application_Error
event handler writes detailed
information to the event log and then displays the message contained
in the userFriendlyMessage
property of the
exception. This example event code is actually a variation of the
event code described in Recipe 7.3,
modified to check whether the exception being processed has a
user-friendly message to use instead of the raw exception message.
This recipe’s approach can be extended many ways to
suite your needs. For example, the custom exception class could
contain a "nextPage
" property that could be set to
pass information on where the user should be taken after reviewing
the error message.
Example 7-10. Custom exception class with user-friendly message property (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH07FriendlyExceptionVB.vb ' ' Description: This class provides an exception class with support for a ' user friendly message ' '***************************************************************************** Imports System Namespace ASPNetCookbook.VBFriendlyException Public Class CH07FriendlyExceptionVB Inherits System.ApplicationException'private copy of user friendly message
Private mUserFriendlyMessage As String = ""
'************************************************************************* ' ' ROUTINE: Property userFriendlyMessage ' ' DESCRIPTION: Provides access to the message to be displayed to the ' user friendly message. '-------------------------------------------------------------------------Public Property userFriendlyMessage( ) As String
Get
Return (mUserFriendlyMessage)
End Get
Set(ByVal Value As String)
mUserFriendlyMessage = Value
End Set
End Property 'userFriendlyMessage
'************************************************************************* ' ' ROUTINE: New ' ' DESCRIPTION: Provides a constructor supporting an error message, a ' reference to the exception that threw this exeception, ' and a user friendly message for the exception '-------------------------------------------------------------------------Public Sub New(ByVal message As String, _
ByVal inner As Exception, _
ByVal userFriendlyMessage As String)
'call base class constructor. NOTE: This must be the first line in
'this constructor
MyBase.New(message, inner)
mUserFriendlyMessage = userFriendlyMessage
End Sub 'New
End Class 'CH07FriendlyExceptionVB End Namespace
Example 7-11. Custom exception class with user-friendly message property (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH07FriendlyExceptionCS.aspx.cs // // Description: This class provides an exception class with support for a // user friendly message // //**************************************************************************** using System; namespace ASPNetCookbook.CSFriendlyException { public class CH07FriendlyExceptionCS : System.ApplicationException {// private copy of user friendly message
private String mUserFriendlyMessage = "";
//************************************************************************ // // ROUTINE: userFriendlyMessage // // DESCRIPTION: Provides access to the message to be displayed to the // user friendly message. //------------------------------------------------------------------------public String userFriendlyMessage
{
get
{
return(mUserFriendlyMessage);
}
set
{
mUserFriendlyMessage = value;
}
} // userFriendlyMessage
//************************************************************************ // // ROUTINE: CH07FriendlyExceptionCS // // DESCRIPTION: Provides a constructor supporting an error message, a // reference to the exception that threw this exeception, // and a user friendly message for the exception. //------------------------------------------------------------------------public CH07FriendlyExceptionCS(String message,
Exception inner,
String userFriendlyMessage) :
base(message, inner)
{
mUserFriendlyMessage = userFriendlyMessage;
}
} // CH07FriendlyExceptionCS }
Example 7-12. Creation of new custom exception (.vb)
Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim values As Hashtable Try 'add a key/value pair to the hashtable without first creating 'the hashtable which will cause a null exception error values.Add("Key", "Value")Catch exc As Exception
Throw New CH07FriendlyExceptionVB(exc.Message, _
exc, _
"The application is currently " & _
"experiencing technical " & _
"difficulties ... " & _
"Please try again later")
End Try End Sub 'Page_Load
Example 7-13. Creation of new custom exception (.cs)
private void Page_Load(object sender, System.EventArgs e) { Hashtable values = null; // wire the page error event this.Error += new System.EventHandler(this.Page_Error); try { // add a key/value pair to the hashtable without first creating // the hashtable which will cause a null exception error values.Add("Key", "Value"); }catch (Exception exc)
{
throw new CH07FriendlyExceptionCS(exc.Message,
exc,
"The application is currently " +
"experiencing technical " +
"difficulties ... " +
"Please try again later");
} } // Page_Load
Example 7-14. Application_Error code for displaying a user-friendly message (.vb)
'************************************************************************* ' ' ROUTINE: Application_Error ' ' DESCRIPTION: This routine provides the event handler for the ' application error event. It is responsible for ' processing errors at the application level. '------------------------------------------------------------------------- Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) Const EVENT_LOG_NAME As String = "Application" Dim lastException As Exception Dim userFriendlyException As CH07FriendlyExceptionVB Dim Log As EventLog Dim message As String 'get the last error that occurred lastException = Server.GetLastError( ) 'create the error message from the message in the last exception along 'with a complete dump of all of the inner exceptions (all exception 'data in the linked list of exceptions) message = lastException.Message & _ vbCrLf & vbCrLf & _ lastException.ToString( ) 'Insert error information into the event log Log = New EventLog Log.Source = EVENT_LOG_NAME Log.WriteEntry(message, _ EventLogEntryType.Error) 'perform other notifications, etc. here'check to if the exception has a user friendly message
If (TypeOf (lastException) Is CH07FriendlyExceptionVB) Then
'exception has a user friendly message
userFriendlyException = CType(lastException, _
CH07FriendlyExceptionVB)
message = userFriendlyException.userFriendlyMessage
Else
'exception does not have a user friendly message to just
'output the raw message
message = lastException.Message
End If
'clear the error and redirect to the page used to display the 'error information Server.ClearError( ) Server.Transfer("CH07DisplayErrorVB.aspx" & _ "?PageHeader=Error Occurred" & _ "&Message1=" & message & _ "&Message2=" & _ "This exception used a user friendly mesage") End Sub 'Application_Error
Example 7-15. Application_Error code for displaying a user-friendly message (.cs)
//************************************************************************ // // ROUTINE: Application_Error // // DESCRIPTION: This routine provides the event handler for the // application error event. It is responsible for // processing errors at the application level. //------------------------------------------------------------------------ protected void Application_Error(Object sender, EventArgs e) { const String EVENT_LOG_NAME = "Application"; Exception lastException = null; CH07FriendlyExceptionCS userFriendlyException = null; EventLog log = null; String message = null; // get the last error that occurred lastException = Server.GetLastError( ); // create the error message from the message in the last exception along // with a complete dump of all of the inner exceptions (all exception // data in the linked list of exceptions) message = lastException.Message + " " + lastException.ToString( ); // Insert error information into the event log log = new EventLog( ); log.Source = EVENT_LOG_NAME; log.WriteEntry(message, EventLogEntryType.Error); // perform other notifications, etc. here// check to if the exception has a user friendly message
if (lastException.GetType( ) == typeof(CH07FriendlyExceptionCS))
{
// exception has a user friendly message
userFriendlyException = (CH07FriendlyExceptionCS)(lastException);
message = userFriendlyException.userFriendlyMessage;
}
else
{
// exception does not have a user friendly message to just
// output the raw message
message = lastException.Message;
}
// clear the error and redirect to the page used to display the // error information Server.ClearError( ); Server.Transfer("CH07DisplayErrorCS.aspx" + "?PageHeader=Error Occurred" + "&Message1=" + message + "&Message2=" + "This exception used a user friendly mesage"); } // Application_Error