Friday, October 1, 2010

How to create custom error reporting pages in ASP.NET

This article describes how to use Visual C# .NET code to trap and respond to errors when they occur in ASP.NET. ASP.NET has improved the error handling options from traditional Microsoft Active Server Pages (ASP). In ASP.NET, you can handle errors at several different levels in your applications.

ASP.NET offers several advances in how you can handle and respond to errors. ASP.NET provides several levels at which you can handle and respond to errors that may occur when you run an ASP.NET application. ASP.NET provides three main methods that allow you to trap and respond to errors when they occur: Page_Error, Application_Error, and the application configuration file (Web.config).

This article demonstrates how to use these new features in your ASP.NET application. Although this article describes how to provide custom error pages and general error reporting as it relates directly to ASP.NET, this article does not describe other error handling approaches such as the try-catch-finally block and the Common Language Runtime (CLR) exception system.

How to use the Page_Error method

The Page_Error event handler provides a way to trap errors that occur at the page level. You can simply display error information (as the sample code to follow does), or you can log the event or perform some other action.

Note This example displays detailed error information in the browser only for demonstration purposes. You will want to be cautious when displaying detailed information to the end user of the application, especially when the application is running on the Internet. A more appropriate action would be to display a message to the user notifying them that an error has occurred, and then actually logging the specific error details in the event log.

This example throws a null exception, which forces an error to occur in the Page_Load event handler. Follow these steps to create the initial page that will demonstrate using the Page_Error event handler.


1.

Follow these steps to add a new file named PageEvent.aspx to your project:


a.

Open Microsoft Visual Studio .NET.

b.

In Solution Explorer, right-click the project node, point to Add, and then click Add Web Form. 

c.

In the Name text box, type PageEvent.aspx, and then click Open.

2.

Add the following code to PageEvent.aspx:


<script language=C# runat="server">

void Page_Load(object sender, System.EventArgs e)

{

      throw(new ArgumentNullException());

}



public void Page_Error(object sender,EventArgs e)

{

      Exception objErr = Server.GetLastError().GetBaseException();

      string err =      "<b>Error Caught in Page_Error event</b><hr><br>" +

                  "<br><b>Error in: </b>" + Request.Url.ToString() +

                  "<br><b>Error Message: </b>" + objErr.Message.ToString()+

                  "<br><b>Stack Trace:</b><br>" +

                        objErr.StackTrace.ToString();

      Response.Write(err.ToString());

      Server.ClearError();

}

</script>




3. 

From the File menu, click Save PageEvent.aspx.

4.

Right-click the page, and then click View in Browser to run the page. Notice that the error is thrown and reported according to the code specifications.
Note You may notice that the code issues a call to Server.ClearError. This prevents the error from continuing to the Application_Error event handler.



How to use the Application_Error method

Similar to the Page_Error event handler, you can use the Application_Error event handler to trap errors that occur in your application. Due to the event's application-wide scope, you can log of application error information or handle other application-level errors that may occur.

The sample to follow is based on the preceding Page_Error code sample and would be fired if the error in Page_Load was not trapped in the Page_Error event handler. The Application_Error event handler is specified in the Global.asax file of your application. For simplicity, the steps in this section create a new page in which to throw the exception, trap the error in the Application_Error event handler of the Global.asax file. The following steps demonstrate how to use the Application_Error method:



1.

Add a new file named AppEvent.aspx to your project.

2.

Add the following code to AppEvent.aspx:

<script language=C# runat="server">

      public void Page_Load(object sender, System.EventArgs e)

      {

            throw(new ArgumentNullException());

      }

</script>



3.

From the File menu, click Save AppEvent.aspx. 

4.

Add the Application_Error event handler to the Global.asax file to trap the error that you throw in the Page_Load event handler of the AppEvent.aspx page.



Add the following code to the Global.asax file:
 

using System.Diagnostics;

void Application_Error(object sender, EventArgs e)

{

        // Code that runs when an unhandled error occurs

        Exception objErr = Server.GetLastError().GetBaseException();

        string err = "Error Caught in Application_Error event\n" +

                "Error in: " + Request.Url.ToString() +

                "\nError Message:" + objErr.Message.ToString() +

                "\nStack Trace:" + objErr.StackTrace.ToString();

        Response.Write(err.ToString());

        Server.ClearError();

        //additional actions...



}




5.

Save the Global.asax file. 

6.

In Visual Studio .NET, on the Build menu, click Build.

7.

Right-click the page, and then click View in Browser. In this case the page will be blank, however, you should notice that a new entry has been added in the event log. This sample makes an entry in the Application log, which is accessible from the Event Viewer. After logging the error you might want to redirect the user to another more user-friendly error page, or perform some additional actions if needed.

How to use the Web.config file

If you do not call Server.ClearError or trap the error in the Page_Error or Application_Error event handler, the error is handled based on the settings in the <customErrors> section of the Web.config file. In the <customErrors> section, you can specify a redirect page as a default error page (defaultRedirect) or specify to a particular page based on the HTTP error code that is raised. You can use this method to customize the error message that the user receives.

If an error occurs that is not trapped at any of the previous levels in your application, this custom page is displayed. This section demonstrates how to modify the Global.asax file so that Server.ClearError is never called. As a result, the error is handled in the Web.config file as the last point to trap the error.


1.

Open the Global.asax file from the previous example. 

2.

Comment out the Server.ClearError line to ensure that the error surfaces in the Web.config file.

3.

Save your changes to Global.asax. Your code should now appear similar to the following:

void Application_Error(object sender, EventArgs e)

    {



        // Code that runs when an unhandled error occurs

        Exception objErr = Server.GetLastError().GetBaseException();

        string err = "Error Caught in Application_Error event\n" +

                "Error in: " + Request.Url.ToString() +

                "\nError Message:" + objErr.Message.ToString() +

                "\nStack Trace:" + objErr.StackTrace.ToString();

        Response.Write(err.ToString());





        //Server.ClearError();

        //additional actions...



    }


4.

Add the following code to the <customErrors> section to redirect the user to a custom page:

<customErrors defaultRedirect="http://hostName/applicationName/errorStatus.htm" mode="On">

</customErrors>




Note You must modify the file path in defaultRedirect attribute so that it references the relevant Web server and application names. 

5. Because the errors that are trapped at this level are sent to a default error page, you must create an error page named ErrorStatus.htm. Keep in mind that you are using this method to control what is presented to the user, so this example uses an .htm page for the error page. Add the following code to ErrorStatus.htm:


<HTML>

<HEAD>

<TITLE></TITLE>

<META NAME="GENERATOR" Content="Microsoft Visual Studio 7.0">

</HEAD>

<BODY>

     <b>Custom Error page!</b>

     <br>

     You have been redirected here from the <customErrors> section of the

     Web.config file.

</BODY>

</HTML>




6.

To test the code, save the files, build the project, and then view AppEvent.aspx in the browser. Notice that when the error is thrown, you are redirected to the ErrorStatus.htm page.
Although you can reference a default error page in the value of the defaultRedirect attribute in the <customErrors> section, you can also specify a particular page to redirect to based on the HTTP error code that is raised. The <error> child element allows for this option. For example:



<customErrors defaultRedirect="http://hostName/applicationName/errorStatus.htm" mode="On">

<error statusCode="404" redirect="filenotfound.htm" /> </customErrors>



Note The page that is specified in defaultRedirect of the <customErrors> section is an .htm file. I



Notice that the <customErrors> section includes a mode attribute that is set to On. The mode attribute is used to control how the error redirection occurs. For example, if you are developing the application, you most likely want to see the actual ASP.NET error messages and do not want to be redirected to the more user-friendly error page. The mode attribute includes the following settings:



On: Unhandled exceptions redirect the user to the specified defaultRedirect page. This mode is used mainly in production.


Off: Users receive the exception information and are not redirected to the defaultRedirect page. This mode is used mainly in development. 


RemoteOnly: Only users who access the site on the local computer (by using localhost) receive the exception information. All other users are redirected to the defaultRedirect page. This mode is used mainly for debugging.

Cascading Style Sheets

Introduction
Cascading Style Sheets (CSS) were introduced by the World Wide Web Consortium to help determine the layout of an HTML document. Removing the formatting from the HTML document allows you to quickly apply a style to a whole site, rather than going through each document and changing the tags that represent the style. It also means that the content of the HTML document isn't bloated by extra information about how data is to be presented.

Specifying Styles within an HTML Document
Styles specified within the document may either apply to the whole document, or a tag contained in the document.

Applying the Style to the whole Document
To apply a style to the whole document, the style information must be placed in the head of the document. The style information is a set of rules that determine how the HTML document is formatted. The following example sets the style for links so they're not underlined and have a colour of black, that turn blue when the mouse is moved over the link. The actual syntax for the style is explained later in this tutorial.

<head>
    <title>Title for this Page</title>
    <style type="text/css">
        a
        {
            text-decoration:none;
            color:#00c;
            background:transparent;
        }
        a:hover
        {
            color:#900;
            background:transparent;
        }
    </style>
</head>

Applying the Style to a Tag
Applying a style directly to a tag is called an inline style. To apply a style to a tag, use the style attribute of the particular tag you want to apply the style to. The following example sets the contents of a cell in a table so that the background colour is light blue.

<td style="background-color:#39C;">content of cell</td>

Further styles maybe added, separated by a semicolon.

<td style="background-color:#39C;font-size:small;">content of cell</td>

External Style Sheets
External style sheets allow you to define a set of rules that can be shared among many HTML documents. This is advantageous in that making a change to the style sheet will automatically be enforced in all of the HTML documents that reference the style sheet.

External style sheets have an extension name of .css and contain a list of rules that are to be applied to any HTML document that references it. The following example may be the contents of a CSS file.

mystylesheet.css

/* Define the style for the body */
body
{
    font: normal 1em/1.2em arial, helvetica, sans-serif;
    color:#000;
    background-color:#fff;
}
/* Define style for links */
a
{
    text-decoration:none;
    color:#00c;
    background:transparent;
}
a:hover
{
    color:#900;
    background:transparent;
}
/* Define a class for links in the menu */
a.menu
{
    text-decoration:none;
    color:#000;
    padding:2px;
    border-bottom:#cc9 2px solid;
    border-right:#cc9 2px solid;
    background:#ffc;
    font-size:large;
}
a.menu:hover
{
    color:#000;
    border-bottom:#603 2px solid;
    border-right:#603 2px solid;
    background:#ffc;
}

Linking to the Style Sheet
For an HTML file to use an external style sheet, there must be a link element in the head of the HTML document specifying the style sheet to use. Depending on how you link to the external style sheet, there are three different relationships it may have with the document, persistent, preferred, and alternate. A mixture of the linking techniques may be applied, as more than one style sheet may be specified for a document.

Persistent Style Sheets
A persistent style sheet is always enabled. If the rules for a document are contained in a single style sheet, then this is the way you will link to the style sheet. If the document has more than one style sheet associated with it, the basic rules may be placed in this style sheet. The relationship is specified with a rel attribute value of, "stylesheet", and no title attribute is provided.

<head>
  <title>Title for this Page</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <link href="mystylesheet.css" rel="stylesheet" type="text/css">
</head>

Preferred Style Sheets
A preferred style sheet is enabled by default, but may be switched by the user for an alternate style sheet. A preferred relationship is specified with a rel attribute value of, "stylesheet", and a title attribute is also provided. You may specify more than one preferred style sheet by specifying the same title for each. The preferred style sheets will be grouped, and enabled and disabled together. If more than one group of preferred style sheets are specified, the first group will take precendence over the other groups.

Alternate Style Sheets
An alternate style sheet is one that may be selected by the visitor as an alternative to the preferred style sheet. An alternate relationship is specified with a rel attribute value of, "alternate stylesheet", and a title attribute is also provided. Like preferred style sheets, alternate style sheets may be grouped by giving them the same title.

The following example uses a persistent, preferred, and alternate style sheet, allowing the visitor to customise the look of the site to their taste.

<head>
  <title>Title for this Page</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <link href="persistent.css" rel="stylesheet" type="text/css">
  <link href="preferred.css" rel="stylesheet" title="Olive" type="text/css">
  <link href="alternate.css" rel="alternate stylesheet" title="Yellow" type="text/css">
</head>

Importing Style Sheets
CSS defines special rules using the @ character. This may be used to import a style sheet, between inline style tags. This is useful for specifying complex rules for non-standards compliant browsers, as they won't understand the import command. The final example defines the relationship with the external style sheets above, but also imports a style sheet that defines rules for layout.

<head>
  <title>Title for this Page</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <link href="persistent.css" rel="stylesheet" type="text/css">
  <link href="preferred.css" rel="stylesheet" title="Olive" type="text/css">
  <link href="alternate.css" rel="alternate stylesheet" title="Yellow" type="text/css">
  <style type="text/css">@import "layout.css";</style>
</head>

Priority of Styles
Styles may be specified in an external document, within the HTML document's <head> region, and inside an HTML tag. More than one style may be specified for an HTML tag, in which case the order of priority is important.

Priority of Styles
A style defined in an HTML tag takes precedence over styles defined in the head of the HTML document. Similarly, styles defined in the head of the HTML document take precedence over styles defined in an external style sheet.

The following style sheet is used to define the <p> tag in the examples below.

mystylesheet.css

p
{
    color:#f00;
    background:transparent;
}

Example 1
In the following example, the definition of the <p> tag within the HTML document will take precedence above the definition of the <p> tag defined within the <head> of the HTML document and the definition of the <p> tag defined in the external style sheet.

example1.html

<html>
<head>
    <title>Title for this Page</title>
    <link href="mystylesheet.css" rel="stylesheet" type="text/css" />
    <style type="text/css">
        p
        {
            color:#0f0;
            background:transparent;
        }
    </style>
</head>
<body>
    <p style="color:#00f;background:transparent;">Blue Text</p>
</body>
</html>

Example 2
In this example, the definition of the <p> tag defined within the <head> of the HTML document will take precedence over the definition of the <p> tag defined in the external style sheet.

example2.html

<html>
<head>
    <title>Title for this Page</title>
    <link href="mystylesheet.css" rel="stylesheet" type="text/css" />
    <style type="text/css">
        p
        {
            color:#0f0;
            background:transparent;
        }
    </style>
</head>
<body>
    <p>Green Text</p>
</body>
</html>
Example 3
This example uses the definition of the <p> tag defined in the external style sheet.

example3.html

<html>
<head>
    <title>Title for this Page</title>
    <link href="mystylesheet.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <p>Red Text</p>
</body>
</html>

Example 4
This final example doesn't specify a style for the <p> tag, so the default style of the browser will be used instead.

example4.html

<html>
<head>
    <title>Title for this Page</title>
</head>
<body>
    <p>Default Browser Text</p>
</body>
</html>

Priorities With the Anchor Element's Pseudo Classes

When specifying styles for the anchor element's psuedo classes, order is important. When you define styles for the same elements, the styles for that element are combined. When there are conflicting styles, the latest one overrides previous definitions of the style (which is inkeeping with the cascading concept, and true for all elements). The least significant style should be written first, and the most significant style written last. With the anchor element, this would be link, visited, hover, then active. If you define a basic style for the anchor element, it should be positioned before the pseudo classes.

Inheritance of Styles
When a style is defined for a tag, the specified properties override the existing properties for that tag. The properties that the original tag had that were not overridden, are inherited into the new style. The following example applies a style to the <h1> tag so that the text is right aligned. If no other style has been specified for the <h1> tag then the browser's default font size, font face, colour, etc is used with the style.

<h1 style="text-align:right">Right-Aligned Text</h1>

Order of Inheritance
The order of inheritance is the same as that of priority. Inheritance within style sheets can be thought of as an inheritance tree consisting of the inline styles, the style sheet in the <head> of the HTML document, and the external style sheet. Any of the styles may be missing, in which case the style above is inherited.

An inline style is inherited from the style defined in the <head> of the document if one exists.
Styles defined in the <head> of the document are inherited from the external style sheet if one exists.
Styles defined in the style sheet are inherited from the browser.
If a style is missing within the inhertance tree, the style is inherited from the style above. For example, If there is no style specified in the <head> of the document or an external style sheet, the style for the <h1> tag defined above would inherit the other properties for <h1> from the browser. If all properties for the tag are overridden, then no inheritance will take place.

Syntax of Styles
Style sheets contain a list of styles, known as rules. The general syntax of a style is as follows:

selector
{
  property: value;
}

The selector may either be an existing tag, or a class. The following example has a selector of p, a property of color, and background, with the values #00f and transparent respectively.

p {
  color: #00f;
  background: transparent;
}

The means that when the <p> tag is used, the colour will be applied from the above style definition.

Using Comments
You can add comments to your style sheets. Comments are not only useful for reminding yourself what a particular style does, but also useful for other project members if you're working in a project group. A comment is anything between /* and */.

p {
  /* Set the colour to Blue for the paragraph tag */
  color: #00f;
  background: transparent;
}

Grouping Selectors
If you want to apply a style to a range of selectors, you can do so by separating them by commas in the selector section. The following example sets the foreground and background colour for a paragraph, and a table column.

p, td {
  color: #000;
  background-color: #fff;
}

Classes
The class attribute is uselful for defining different styles for the same tag. The name of the class is separated from the tag using a period. The class name is then specified to determine which class of the tag is required in the HTML document.

The following example defines three classes of style to be used with the <p> tag.

p.red {
  color: #f00;
  background: transparent;
}
p.green {
  color: #0f0;
  background: transparent;
}
p.blue {
  color: #00f;
  background: transparent;
}

The HTML document can now reference the class of the <p> tag to apply that particular style.

<p class="red">
  This paragraph is red
</p>
<p class="green">
  This paragraph is green
</p>
<p class="blue">
  This paragraph is blue
</p>

If you want to define a class that can be used on a range of tags, you can do so by not specifying the tag name as in the following example.

.whiteOnBlue {
  color: #fff;
  background-color: #39C;
}

You can then use the class in an appropriate html tag. The following example uses the whiteOnBlue class in a <p> tag.

<p class="whiteOnBlue">This text is white, on a blue background</p>

The next example uses the whiteOnBlue class in a <td> tag.

<table border="0" cellpadding="5" cellspacing="0">
<tr>
  <td>Left</td>
  <td class="whiteOnBlue">This text is white, on a blue background</td>
  <td>Right</td>
</tr>
</table>

ID Selectors
All id attributes in an (X)HTML document must be unique. You may specify styles for an id by specifying a # immediately before the id value. This effectively allows you to specify a style for a single instance of an element in the document tree, which is useful for laying out documents.

The following example defines a style for a paragraph with an id of "firstPara".

p#firstPara {
  font-size: large;
}

The style would then be used in the document as follows.

<p id="firstPara">
  This paragraph has been specified with an id attribute, and so may only appear once in the document.
</p>

The following example specifies styles that may be used for layout purposes.

#navBar {
  float: left;
  width: 15%;
  color: #000;
  background: #fff;
  border-right: 1px solid #cc9;
  border-bottom: 1px solid #cc9;
  padding: 10px;
}
#mainContent {
  float: left;
  width: 80%;
  color: #000;
  background: #fff;
  padding: 10px;
}

The styles may then be used in the document to create a two column effect as follows.

<div id="navBar">
  Navigation links in here
</div>
<div id="mainContent">
  Main content in here
</div>