Responding to Errors


Four main types of errors can occur in an ASP.NET application:

  • Configuration errors ” Caused by problems in either the Web.Config or the Machine.Config file

  • Parser errors ” Caused by incorrect syntax in an ASP.NET page

  • Compilation errors ” Raised by the Visual Basic compiler

  • Runtime errors ” Detected when the page is actually executing

A configuration error, for example, can be caused by a badly formed Web.Config file like the one in Listing 18.1.

Listing 18.1 ConfigErrors/Web.Config
 <configuration>   <appSettings>     <add key="myKey" value="myValue"/> </configuration> 

The C# version of this code can be found on the CD-ROM.

The problem with the Web.Config file in Listing 18.1 is that it does not include a closing tag that corresponds to the opening <appSettings> tag. If you attempt to open a page from the same directory as the directory that contains this Web.Config file, you receive an error. In this case, a very messy error message ”see Figure 18.1. (You might receive a different error message depending on the version of the .NET Framework installed on your machine.)

Figure 18.1. Receiving a configuration error.

graphics/18fig01.jpg

A parser error is raised when the contents of a page cannot be parsed. For example, the ASP.NET page in Listing 18.2 would generate a parser error (see Figure 18.2).

Listing 18.2 Parser.aspx
 <script Runat="Server"> Sub Page_Load   lblMessage.Text = "hello!" End Sub <html> <head><title>Parser.aspx</title></head> <body> <asp:Label   ID="lblMessage"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Figure 18.2. Receiving a parser error.

graphics/18fig02.jpg

The problem with the page in Listing 18.2 is that it does not include a closing </Script> tag that corresponds with the opening <Script> tag. Parser errors prevent a page from being compiled.

A compilation error is raised when the ASP.NET page is in the process of being compiled. The error is raised by the particular language being used to compile the page (for example, Visual Basic). The page in Listing 18.3 generates a compilation error (see Figure 18.3).

Listing 18.3 Compilation.aspx
 <Script Runat="Server"> Sub Page_Load   lblMessage.Value = "hello!" End Sub </Script> <html> <head><title>Compilation.aspx</title></head> <body> <asp:Label   ID="lblMessage"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Figure 18.3. Receiving a compilation error.

graphics/18fig03.jpg

In the page in Listing 18.3, text is assigned to a Label control's Value attribute. Because a Label control does not have a Value attribute, a compilation error is raised.

Finally, runtime errors occur after a page is successfully compiled. A runtime error is not detected until the page actually executes. The page in Listing 18.4 generates a runtime error (see Figure 18.4).

Listing 18.4 Runtime.aspx
 <Script Runat="Server"> Sub Page_Load   Dim txtTextBox As TextBox   txtTextBox.Text = "hello!" End Sub </Script> <html> <head><title>Runtime.aspx</title></head> <body> <asp:Label   ID="lblMessage"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Figure 18.4. Receiving a runtime error.

graphics/18fig04.jpg

In the Page_Load subroutine in Listing 18.4, a TextBox control is declared, and text is assigned to the TextBox control's Text property. This assignment generates a Null Reference Exception because the TextBox control wasn't instantiated before a value was assigned to one of its properties.

Viewing Error Information

Two configuration settings affect how error information is displayed:

  • Custom errors mode ” This setting enables or disables custom errors. When custom errors mode is enabled, errors on a page are hidden. This setting has three possible values: On , Off , and RemoteOnly .

  • Debug mode ” When debug mode is enabled, additional information for debugging runtime errors is displayed.

You can use custom errors to hide errors from the users of your Web site. When the custom errors mode is assigned the value On , detailed error information is hidden. When the custom errors mode is set to the value Off , all the available error information is displayed. Finally, if you assign the value remoteOnly to custom errors, errors are hidden when requested with a browser on a remote machine, but the errors are displayed when requested with a browser located on the same machine as the Web server.

If you need to view detailed error information, you need to disable custom errors or set this mode to the value RemoteOnly . You can configure the custom errors mode in either the Machine.Config file or a Web.Config file located within a particular application. The Web.Config file in Listing 18.5, for example, sets customErrors to the value Off .

Listing 18.5 CustomErrorsOff/Web.Config
 <configuration>   <system.web>     <customErrors mode="Off" />   </system.web> </configuration> 

The C# version of this code can be found on the CD-ROM.

When the custom errors mode is set to the value Off , detailed error information is always displayed, even on remote computers. (Always displaying this information can be a security risk.) You might want to disable custom errors while developing an ASP.NET application and before placing the site into production.

The second configuration setting, debug mode, controls whether pages are compiled in debug mode. When pages are compiled in this mode, additional debugging information is included with the compiled code. This mode displays more detailed error information when a runtime error occurs.

NOTE

You can enable debug mode to display additional information for runtime errors. This setting has no effect on the display of parser or compilation errors.


When you enable debug mode, ASP.NET pages are compiled with the Visual Basic compiler's /debug+ compiler option. The source code for the ASP.NET page and detailed compiler output generated by compiling the page are written to files in the Temporary ASP.NET Files directory.

CAUTION

Never enable debug mode for a production Web site. Placing an application in debug mode results in a severe performance penalty.


You can choose from two methods to enable debug mode for an ASP.NET page. You can enable debug mode for all the pages in a directory in the Web.Config file, or you can enable it for a single page by using a page directive. For example, the page in Listing 18.6 uses a page directive to enable debug mode.

Listing 18.6 Debug.aspx
 <%@ Page Debug="True" %> <Script Runat="Server"> Sub Page_Load   Dim txtTextBox As TextBox   txtTextBox.Text = "hello!" End Sub </Script> <html> <head><title>Debug.aspx</title></head> <body> <h2>This page has an error!</h2> </body> </html> 

The C# version of this code can be found on the CD-ROM.

When you request the page in Listing 18.6 with debug mode enabled, you see the page in Figure 18.5. When debug mode is disabled, on the other hand, you see the page in Figure 18.6.

Figure 18.5. Page with debug mode enabled.

graphics/18fig05.jpg

Figure 18.6. Page with debug mode disabled.

graphics/18fig06.jpg

You can enable or disable debug mode for all the pages in an application by adding the Web.Config file in Listing 18.7 to the root directory of the application.

Listing 18.7 /DebugMode/Web.Config
 <configuration>   <system.web>     <customErrors mode="Off" />     <compilation debug="true" />   </system.web> </configuration> 

The C# version of this code can be found on the CD-ROM.

The Web.Config file in Listing 18.7 enables debug mode by setting the debug attribute of the compilation configuration setting to the value true . It also disables custom errors when pages are requested from the local machine so that error information can be viewed .

Page-Level Error Handling

In the following sections, you learn how to capture and handle errors that occur in an ASP.NET page. First, you learn how to use the Visual Basic TRY...CATCH statement to wrap dangerous statements in error handling code. Next, you learn how to capture and respond to unhandled errors that occur in a page by using the Page_Error subroutine.

Catching Exceptions with TRY...CATCH

Whenever you need to execute a statement that might fail, it is a good idea to wrap the statement in a Visual Basic TRY...CATCH block. If you place a dangerous statement in a TRY...CATCH block, you can programmatically handle any runtime errors that result from executing the statement.

The page in Listing 18.8, for example, uses a TRY...CATCH block when opening a database connection.

Listing 18.8 TryCatch.aspx
[View full width]
 <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Page_Load   Dim conNorthwind As SqlConnection   Dim cmdSelect As SqlCommand   conNorthwind = New SqlConnection( "Server=localhost;UID=sa;pwd=secret; graphics/ccc.gif Database=Northwind;Connection TimeOut=15" )   cmdSelect = New SqlCommand( "select * from Products", conNorthwind )   Try   conNorthwind.Open     dgrdProducts.DataSource = cmdSelect.ExecuteReader()     dgrdProducts.DataBind()   conNorthwind.Close   Catch     Response.Write( "We're sorry, we are experiencing technical problems..." )   End Try End Sub </Script> <html> <head><title>TryCatch.aspx</title></head> <body> <asp:DataGrid   ID="dgrdProducts"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

In the Page_Load subroutine in Listing 18.8, a connection to a SQL Server database named Northwind is opened. The Open method for the SQLConnection object is called within a TRY block. If the connection cannot be opened ”for example, the database server is offline ”the statement in the CATCH block is executed. This statement simply displays a message reporting technical difficulties.

You could, of course, perform other actions in the CATCH block. For example, you could switch to a backup database or automatically send an email to the Webmaster.

If you need to retrieve error information within the CATCH block, you can catch the exception that raised the error. Exceptions are represented within the .NET framework with instances of the Exception class. This class includes the following properties:

  • Message ” Returns a string that represents the error message

  • Source ” Returns a string representing the object or application that caused the error

  • StackTrace ” Returns a string that represents the methods called immediately before the error occurred

  • TargetSite ” Returns a MethodBase object that represents the method that caused the error

The page in Listing 18.9, for example, displays the values of these properties when an error occurs.

Listing 18.9 CatchException.aspx
[View full width]
 <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Page_Load   Dim conNorthwind As SqlConnection   Dim cmdSelect As SqlCommand   conNorthwind = New SqlConnection( "Server=localhost;UID=sa;pwd=secret; graphics/ccc.gif Database=Northwind;Connection Timeout=15" )   cmdSelect = New SqlCommand( "select * from Products", conNorthwind )   Try   conNorthwind.Open     dgrdProducts.DataSource = cmdSelect.ExecuteReader     dgrdProducts.DataBind()   conNorthwind.Close   Catch objException As Exception     Response.Write( "We're sorry, we are experiencing technical problems..." )     Response.Write( "<hr>" )     Response.Write( "<li> Message: " & objException.Message )     Response.Write( "<li> Source: " & objException.Source )     Response.Write( "<li> Stack Trace: " & objException.StackTrace )     Response.Write( "<li> Target Site: " & objException.TargetSite.Name )   End Try End Sub </Script> <html> <head><title>CatchException.aspx</title></head> <body> <asp:DataGrid   ID="dgrdProducts"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

The Exception object represents a generic exception. You also can use the CATCH statement with particular exceptions. You might want to do so if you need to gather more specific information on the cause of an error. For example, the page in Listing 18.10 uses the CATCH statement with the SqlException class.

Listing 18.10 SqlException.aspx
[View full width]
 <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Page_Load   Dim conNorthwind As SqlConnection   Dim cmdSelect As SqlCommand   conNorthwind = New SqlConnection( "Server=localhost;UID=sa;pwd=secret; graphics/ccc.gif Database=Northwind;Connection TimeOut=15" )   cmdSelect = New SqlCommand( "select * from BadTable", conNorthwind )   Try   conNorthwind.Open()     dgrdProducts.DataSource = cmdSelect.ExecuteReader     dgrdProducts.DataBind()   conNorthwind.Close   Catch objException As SqlException     Dim objError As SqlError     For each objError in objException.Errors       Response.Write( "<li>" & objError.Message )     Next   End Try End Sub </Script> <html> <head><title>SqlException.aspx</title></head> <body> <asp:DataGrid   ID="dgrdProducts"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

In the CATCH statement in Listing 18.10, an instance of the SqlException class is caught. Next, detailed error information is displayed for the SQL Exception by looping through the SQL Exception's Errors collection.

NOTE

The .NET Framework SDK Documentation lists the particular exceptions raised by the properties and methods of each class.


The TRY...CATCH statement includes an optional FINALLY clause. Any statements contained in the FINALLY clause are guaranteed to execute whether or not an exception has occurred. For example, in the following statements, the FINALLY clause closes the database connection, regardless of whether an error occurred:

 
 Try   dgrdProducts.DataSource = cmdSelect.ExecuteReader()   dgrdProducts.DataBind() Catch objException As Exception   Response.Write( "Could Not Execute Statement!" ) Finally   conNorthwind.Close End Try 
Catching Unhandled Exceptions in a Page

You can catch and handle any error that occurs in a page by creating a Page_Error subroutine, which is executed whenever an unhandled exception occurs.

The page in Listing 18.11, for example, uses the Page_Error subroutine to display a quick apology, display the error message, and clear the exception that raised the error.

Listing 18.11 PageError.aspx
 <Script Runat="Server"> Sub Page_Error   Response.Write( "Sorry, there was an error:" )   Response.Write( "<p>" )   Response.Write( Server.GetLastError.Message )   Server.ClearError() End Sub Sub Page_Load   Dim txtTextBox As TextBox   txtTextBox.Text = "Hello World!" End Sub </Script> <html> <head><title>PageError.aspx</title></head> <body> <h2>This page contains an error!</h2> </body> </html> 

The C# version of this code can be found on the CD-ROM.

The Page_Error subroutine in Listing 18.11 takes advantage of two methods of the HttpServerUtility class: GetLastError and ClearError .

The GetLastError method returns the last exception thrown. In the page in Listing 18.11, the GetLastError method displays the value of the Message property of the last exception thrown.

The ClearError method clears the last exception thrown. If you didn't call the ClearError method in the page in Listing 18.11, the default error page generated by the ASP.NET framework would be displayed, and no one would ever see the polite apology.

Application-Level Error Handling

In the following sections, you learn how to handle errors in your ASP.NET pages no matter where they occur within an application. You also learn how to enable and configure custom errors in the Web.Config file and create a global error handler in the Global.asax file.

Using Custom Errors

You can use custom errors to hide errors in your ASP.NET application from your users, or to display more user -friendly error messages. After you enable custom errors, you can automatically redirect users to an error page whenever an unhandled error occurs.

You configure custom errors within the customErrors section of the Web.Config file. This section contains error elements that associate particular errors with error pages. For example, the Web.Config file in Listing 18.12 handles both application errors and Page Not Found errors.

Listing 18.12 CustomErrors/Web.Config
 <configuration>   <system.web>     <customErrors mode="On" defaultRedirect="AppError.aspx">       <error statusCode="404" redirect="NotFound.aspx" />       <error statusCode="500" redirect="AppError.aspx" />     </customErrors>   </system.web> </configuration> 

The C# version of this code can be found on the CD-ROM.

The Web.Config file in Listing 18.11 associates 404 ” Page Not Found ”errors with the NotFound.aspx page. Page errors with the status code 500 ” Internal Server Errors ”are associated with the AppError.aspx page. Finally, the defaultRedirect attribute associates any other error with the AppError.aspx page.

If you request a page and a page with that name does not exist on the Web server, you are automatically redirected to the NotFound.aspx page.

When you are redirected to a page with custom errors, a query string variable is automatically passed to the error page. The query string variable, named aspxerrorpath , contains the path of the page that was originally requested. For example, the page in Listing 18.13 illustrates how you can use the aspxerrorpath query string variable to display a simple error message.

Listing 18.13 NotFound.aspx
 <Script Runat="Server"> Sub Page_Load   lblMessage.Text = Request.Params( "aspxerrorpath" )   lblMessage.Text &= " does not exist!" End Sub </Script> <html> <head><title>NotFound.aspx</title></head> <body> <asp:Label   ID="lblMessage"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

If you prefer, you also can enable custom errors on a page-by-page basis. You can specify an error page for a particular page by using either the ErrorPage page directive or the ErrorPage page property.

If a runtime error occurs when the page in Listing 18.14 is requested, for example, the user is automatically redirected to the AppError.aspx page (this page can be found in the ErrorPage subdirectory).

Listing 18.14 ErrorPage/ErrorPage.aspx
 <%@ Page ErrorPage="AppError.aspx" %> <Script Runat="Server"> Sub Page_Load   Dim txtTextBox As TextBox   txtTextBox.Text = "Hello" End Sub </Script> <html> <head><title>ErrorPage.aspx</title></head> <body> <h2>This page contains an error!</h2> </body> </html> 

The C# version of this code can be found on the CD-ROM.

In Listing 18.14, the ErrorPage attribute contained in the page directive points to a page named AppError.aspx . If an unhandled error is thrown in the page, the user is automatically redirected to this page.

It's important to understand that the ErrorPage attribute works only when the custom errors mode has been enabled for the application. The custom errors configuration setting must have the value on or remoteOnly in the Web.Config or Machine.Config file for the ErrorPage attribute to work.

Handling Errors in the Global.asax File

In the Global.asax file, you can create a single subroutine that is triggered by any unhandled exception thrown on any page. To do so, you simply need to add an Application_Error subroutine to the file.

The Global.asax file in Listing 18.15, for example, contains an Application_Error subroutine that automatically emails the Webmaster of the Web site whenever an error occurs in a page.

Listing 18.15 GlobalError/Global.asax
 <%@ Import Namespace="System.Web.Mail" %> <Script Runat="Server"> Sub Application_Error   Dim objMail As New MailMessage   objMail.From = "website@yourdomain.com"   objMail.To = "Webmaster@yourdomain.com"   objMail.Subject = "Error at Web site"   objMail.Body = Request.Path   objMail.Body &= vbNewLine   objMail.Body &= Context.Server.GetLastError.Message   SmtpMail.Send( objMail )   Context.Server.ClearError() End Sub </Script> 

The C# version of this code can be found on the CD-ROM.

If you add the file in Listing 18.15 to your application root directory, an email is sent to Webmaster@yourdomain.com whenever an error occurs in any page within the application.

NOTE

To learn more details about sending email in an ASP.NET application, see Chapter 26, "Sending Email and Accessing the Network."




ASP.NET Unleashed
ASP.NET 4 Unleashed
ISBN: 0672331128
EAN: 2147483647
Year: 2003
Pages: 263

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net