Error Handling in ASP

153
Error Handling in ASP.NET... In anything but the simplest of cases your application will contain errors. You should identify where errors might be likely to occur and code to anticpate and handle them gracefully. By: Chris Sully Date: March 30, 2003 Printer Friendly Version Introduction I came to the realisation a little time ago that I really wasn’t making the most of the error handling facilities of ASP.NET. The sum of my ASP.Net error handling knowledge up until that point was the new (to VB) Try … Catch … Finally construct at the page level. While I shall examine this new addition there are more facilities at our disposal and this article shall share the results of my recent investigations. In anything but the simplest of cases your application WILL contain errors. You should identify where errors might be likely to occur and code to anticipate and handle them gracefully. The .NET Framework’s Common Language Runtime (CLR) implements exception handling as one of its fundamental features. As you might expect due to the language independence of the framework you can also write error handling in VB.NET that can handle errors in C# code, for example. The exception object thrown is of the same primitive type (System.Exception). Options … Options (preventing runtime errors) If we can we should capture errors as early as possible as fewer will then make it through to the runtime environment. VB.Net offers the Option Strict and Option Explicit statements to prevent errors at design time.

Transcript of Error Handling in ASP

Page 1: Error Handling in ASP

Error Handling in ASP.NET...

In anything but the simplest of cases your application will contain errors. You should identify where errors might be likely to occur and code to anticpate and handle them gracefully.

By: Chris Sully Date: March 30, 2003 Printer Friendly Version

Introduction

I came to the realisation a little time ago that I really wasn’t making the most of the error handling facilities of ASP.NET. The sum of my ASP.Net error handling knowledge up until that point was the new (to VB) Try … Catch … Finally construct at the page level. While I shall examine this new addition there are more facilities at our disposal and this article shall share the results of my recent investigations.

In anything but the simplest of cases your application WILL contain errors. You should identify where errors might be likely to occur and code to anticipate and handle them gracefully.

The .NET Framework’s Common Language Runtime (CLR) implements exception handling as one of its fundamental features. As you might expect due to the language independence of the framework you can also write error handling in VB.NET that can handle errors in C# code, for example. The exception object thrown is of the same primitive type (System.Exception).

Options … Options (preventing runtime errors)

If we can we should capture errors as early as possible as fewer will then make it through to the runtime environment. VB.Net offers the Option Strict and Option Explicit statements to prevent errors at design time.

Classic ASP programmers should be familiar with Option Explicit – it forces explicit declaration of all variables at the module level. In addition when programming ASP.NET pages in VB.NET when Option Explicit is enabled, you must declare all variables using Public, Private, Dim or Redim.

The obvious mistake that Option Explicit captures is using the same variable name multiple times within the same scope … a situation which is very likely to lead to runtime errors, if not exceptions.

Thankfully, in ASP.NET Option Explicit is set to on by default. If for any reason you did need to reset, the syntax is:

Option Explicit Off

Page 2: Error Handling in ASP

at the top of a code module or

<%@ Page Explicit=”False”%>

in a web form.

Enabling Option Strict causes errors to be raised if you attempt a data type conversion that leads to a loss in data. Thus, if this lost data is of potential importance to your application Option Strict should be enabled. Option Strict is said to only allow ‘widening’ conversions, where the target data type is able to accommodate a greater amount of data than that being converted from.

The syntax is as per Option Explicit.

Exceptions

What precisely is an exception? The exception class is a member of the System namespace and is the base class for all exceptions. Its two sub-classes are the SystemException class and the ApplicationException class.

The SystemException class defines the base class for all .NET predefined exceptions. One I commonly encounter is the SQLException class, typically when I haven’t quite specified my stored procedure parameters correctly in line with the stored procedure itself.

When an exception object is thrown that is derived from the System.Exception class you can obtain information from it regarding the exception that occurred. For example, the following properties are exposed:

HelpLink Gets or sets a link to the help file associated with this exception.

InnerException Gets the Exception instance that caused the current exception.

Message Gets a message that describes the current exception.

Source Gets or sets the name of the application or the object that causes the error.

StackTraceGets a string representation of the frames on the call stack at the time the current exception was thrown.

TargetSite Gets the method that throws the current exception.

See the SDK documentation for more information.

The ApplicationException class allows you to define your own exceptions. It contains all the same properties and methods as the SystemException class. We shall return to creating such custom exceptions after examining the main error handling construct at our disposal: 'Try … Catch … Finally'.

Structured and Unstructured Error Handling

Page 3: Error Handling in ASP

Previous versions of VB had only unstructured error handling. This is the method of using a single error handler within a method that catches all exceptions. It’s messy and limited. Briefly, VB’s unstructured error handlers (still supported) are:

On Error GoTo line[or]labelOn Error Resume NextOn Error GoTo 0On Error GoTo -1

But forget about these as we now have new and improved C++ like structured exception handling with the Try ... Catch … Finally construct, as follows:

Try  [ tryStatements ][ Catch [ exception [ As type ] ] [ When expression ]   [ catchStatements ] ][ Exit Try ]...[ Finally  [ finallyStatements ] ]End Try

Thus we try to execute some code; if this code raises an exception the runtime will check to see if the exception is handled by any of the Catch blocks in order. Finally we may execute some cleanup code, as appropriate. Exit Try optionally allows us to break out of the construct and continue executing code after End Try. When optionally allows specification of an additional condition which must evaluate to true for the Catch block to be executed.

Here’s my code snippet for SQL server operations by way of a simple, and not particularly good (see later comments), example:

Try myConnection.open() myCommand = new SQLCommand("USP_GENERIC_select_event_dates", myConnection) myCommand.CommandType = CommandType.StoredProcedure myCommand.Parameters.Add(New SQLParameter("@EventId",SQLDBType.int)) myCommand.Parameters("@EventId").value=EventId objDataReader=myCommand.ExecuteReader() Catch objError As Exception 'display error details outError.InnerHtml = "<b>* Error while executing data command (ADMIN: Select Event Dates)</b>.<br />" _ & objError.Message & "<br />" & objError.Source & _

Page 4: Error Handling in ASP

". Please <a href='mailto:[email protected]'>e-mail us</a> providing as much detail as possible including the error message, what page you were viewing and what you were trying to achieve.<p /><p />" Exit Function ' and stop execution End Try

There are several problems with this code as far as best practice is concerned, the more general of which I’ll leave to the reader to pick up from the following text, but in particular there should be a Finally section which tidies up the database objects.

Note it is good form to have multiple Catch blocks to catch different types of possible exceptions. The order of the Catch blocks affects the possible outcome … they are checked in order.

You can also throw your own exceptions for the construct to deal with; or re-throw existing exceptions so they are dealt with elsewhere. See the next section for a little more detail.

You could just have a Catch block that trapped general exceptions – exception type ‘exception’ (see above!). This is not recommended as it suggests a laziness to consider likely errors. The initial catch blocks should be for possible specific errors with a general exception catch block as a last resort if not covered by earlier blocks.

For example, if accessing SQLServer you know that a SQLException is possible. If you know an object may return a null value and will cause an exception, you can handle it gracefully by writing a specific catch statement for a NullReferenceException.

For you information here’s a list of the predefined exception types provided by the .NET Runtime:

Exception type Base type Description Example

Exception ObjectBase class for all exceptions.

None (use a derived class of this exception).

SystemException Exception

Base class for all runtime-generated errors.

None (use a derived class of this exception).

IndexOutOfRangeException SystemException

Thrown by the runtime only when an array is indexed improperly.

Indexing an array outside its valid range: arr[arr.Length+1]

NullReferenceException SystemException Thrown by the runtime only

object o = null; o.ToString();

Page 5: Error Handling in ASP

when a null object is referenced.

InvalidOperationException SystemException

Thrown by methods when in an invalid state.

Calling Enumerator.GetNext() after removing an Item from the underlying collection.

ArgumentException SystemExceptionBase class for all argument exceptions.

None (use a derived class of this exception).

ArgumentNullException ArgumentException

Thrown by methods that do not allow an argument to be null.

String s = null; "Calculate".IndexOf (s);

ArgumentOutOfRangeException ArgumentException

Thrown by methods that verify that arguments are in a given range.

String s = "string"; s.Chars[9];

ExternalException SystemException

Base class for exceptions that occur or are targeted at environments outside the runtime.

None (use a derived class of this exception).

ComException ExternalException

Exception encapsulating COM HRESULT information.

Used in COM interop.

SEHException ExternalException

Exception encapsulating Win32 structured exception handling information.

Used in unmanaged code interop.

Page 6: Error Handling in ASP

Throwing Exceptions

As indicated earlier, not only can you react to raised exceptions, you can throw exceptions too when needed. For example, you may wish to re-throw an exception after catching it and not being able to recover from the exception. Your application-level error handling could then redirect to an appropriate error page.

You may further wish to throw your own custom exceptions in reaction to error conditions in your code.

The syntax is

Throw new [Exception]

Creating Custom Exceptions

As mentioned earlier, via the ApplicationException class you have the ability to create your own exception types.

Here’s an example VB class to do just that:

Imports System Imports System.Text Namespace CustomExceptions Public Class customException1: Inherits ApplicationException Public Sub New() MyBase.New("<H4>Custom Exception</H4><BR>") Dim strBuild As New StringBuilder() strBuild.Append("<p COLOR='RED'>") strBuild.Append("For more information ") strBuild.Append("please visit: ") strBuild.Append("<a href='http://www.cymru-web.net/exceptions'>") strBuild.Append("Cymru-Web.net</a></p>") MyBase.HelpLink = strBuild.ToString() End Sub End Class End Namespace

Looking at this code. On line 6 you see that to create a custom exception we must inherit from the ApplicationException class. In the initialization code for the class we construct a new ApplicationException object using a string (one of the overloaded constructors of ApplicationException – see the .NET documentation for details of the others). We also set the

Page 7: Error Handling in ASP

HelpLink property string for the exception – this is a user friendly message for presentation to any client application.

The MyBase keyword behaves like an object variable referring to the base class of the current instance of a class (ApplicationException). MyBase is commonly used to access base class members that are overridden or shadowed in a derived class. In particular, MyBase.New is used to explicitly call a base class constructor from a derived class constructor.

Next a small test client, written in VB.NET using Visual Studio.Net so we have both web form and code behind files:

WebForm1.aspx:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="article_error_handling.WebForm1"%> <html> <body> </body> </html>

WebForm1.aspx.vb

Imports article_error_handling.CustomExceptions Public Class WebForm1 Inherits System.Web.UI.Page Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Try Throw New customException1() Catch ex As customException1 Response.Write(ex.Message & " " & ex.HelpLink) End Try End Sub End Class

This (admittedly simple) example you can extend to your own requirements.

Page Level Error Handling

Two facets:

1. Page redirection2. Using the Page objects error event to capture exceptions

Taking each in turn:

Page 8: Error Handling in ASP

Page redirection

Unforeseen errors can be trapped with the ErrorPage property of the Page object. This allows definition of a redirection URL in case of unhandled exceptions. A second step is required to enable such error trapping however – setting of the customErrors attribute of your web.config file, as follows:

<configuration> <system.web> <customErrors mode="On"> </customErrors> </system.web> </configuration>

Then you’ll get your page level redirection rather than the page itself returning an error, so the following would work:

<%@ Page ErrorPage="http://www.cymru-web.net/GenericError.htm" %>

A useful option in addition to ‘on’ and ‘off’ for the mode attribute of customErrors is ‘RemoteOnly’ as when specified redirection will only occur if the browser application is running on a remote computer. This allows those with access to the local computer to continue to see the actual errors raised.

Page Objects Error Event

The Page object has an error event that is fired when an unhandled exception occurs in the page. It is not fired if the exception is handled in the code for the page. The relevant sub is Page_Error which you can use in your page as illustrated by the following code snippet:

Sub Page_Error(sender as Object, e as EventArgs) dim PageException as string = Server.GetLastError().ToString() dim strBuild as new StringBuilder() strBuild.Append("Exception!") strBuild.Append(PageException) Response.Write(strBuild.ToString()) Context.ClearError() End Sub

As with page redirection this allows you to handle unexpected errors in a more user-friendly fashion. We’ll return to explain some of the classes used in the snippet above when we look at a similar scenario at the application level in the next section.

Application Level Error Handling

Page 9: Error Handling in ASP

In reality you are more likely to use application level error handling rather than the page level just introduced. The Application_Error event of the global.asax exists for this purpose. Unsurprisingly, this is fired when an exception occurs in the corresponding web application.

In the global.asx you code against the event as follows:

Sub Application_Error(sender as Object, e as EventArgs) 'Do Something End Sub

Unfortunately the EventArgs in this instance are unlikely to be sufficiently informative but there are alternative avenues including that introduced in the code of the last section – the HttpServerUtility.GetLastError method which returns a reference to the last error thrown in the application. This can be used as follows:

Sub Application_Error(sender as Object, e as EventArgs) dim LastException as string = Server.GetLastError().ToString() Context.ClearError() Response.Write(LastException) End Sub

Note that the ClearError method of the Context class clears all exceptions from the current request – if you don’t clear it the normal exception processing and consequent presentation will still occur.

Alternatively there is the HttpContext’s class Error property which returns a reference to the first exception thrown for the current HTTP request/ response. An example:

Sub Application_Error(sender as Object, e as EventArgs) dim LastException as string = Context.Error.ToString() Context.ClearError() Response.Redirect("CustomErrors.aspx?Err=" & Server.UrlEncode(LastException)) End Sub

This illustrates one method for handling application errors – redirection to a custom error page which can then customise the output to the user dependent on the actual error received.

Finally, we also have the ability to implement an application wide error page redirect, via the customErrors section of web.config already introduced, using the defaultRedirect property:

<configuration> <system.web>

Page 10: Error Handling in ASP

<customErrors mode="on" defaultRedirect="customerrors.aspx?err=Unspecified"> <error statusCode="404" redirect="customerrors.aspx?err=File+Not+Found"/> </customErrors> </system.web> </configuration>

Note this also demonstrates customised redirection via the error attribute. The HttpStatusCode enumeration holds the possible values of statusCode. This is too long a list to present here - see the SDK documentation.

Conclusion

I hope this has provided a useful introduction to the error handling facilities of ASP.NET. I further hope you’ll now go away and produce better code that makes use of these facilities! In summary:

Trap possible errors at design time via Option Explicit and Option Strict. Consider in detail the possible errors that could occur in your application.

Use the Try … Catch … Finally construct to trap these errors at the page level and elsewhere.

It is generally considered poor programming practice to use exceptions for anything except unusual but anticipated problems that are beyond your programmatic control (such as losing a network connection). Exceptions should not be used to handle programming bugs!

Use application level exception handling (and perhaps also Page level) to trap foreseen and unforeseen errors in a user friendly way.

ASP.NETComplete Example for Error Handlers

The example consists of the following files:

Web.config Global.asax

Default.aspx

ExceptionUtility (to be put in the App_Code folder)

GenericErrorPage.aspx

HttpErrorPage.aspx

Page 11: Error Handling in ASP

Http404ErrorPage.aspx

DefaultRedirectErrorPage.aspx

Web.config

The following example shows the Web.config file. The customErrors section specifies how to handle errors that occur with file types that are mapped to ASP.NET, such as .aspx, .asmx, and .ashx files. (In IIS 6.0 and in IIS 7.0 in classic mode, static content files such as .html and .jpg files are not mapped to ASP.NET.)

The settings in the example customErrors section cause any unhandled HTTP 404 (file not found) errors to be directed to the Http404ErrorPage.aspx file. These HTTP 404 errors would occur if a request were made for an .aspx file, .asmx file, and so on and if the requested file did not exist. All other unhandled errors in ASP.NET files are directed to the DefaultRedirectErrorPage.aspx file.

If static content files are not handled by ASP.NET, a request for a nonexistent .html or .jpg file does not cause a redirect to the Http404ErrorPage.aspx file. If you want ASP.NET to handle requests for all file types, you can configure IIS to map file-name extensions to ASP.NET.

Note:In the example, the mode attribute is set to "On" so that you can error messages when you run the example in Visual Studio. In a production environment, this setting would normally be "RemoteOnly". ASP.NET then renders error pages to external users. If a request is made on the server computer (localhost), ASP.NET renders a page with detailed error information.None <configuration> <appSettings/> <connectionStrings/> <system.web> <compilation debug="true" />

<!-- Turn on Custom Errors --> <customErrors mode="On" defaultRedirect="DefaultRedirectErrorPage.aspx"> <error statusCode="404" redirect="Http404ErrorPage.aspx"/> </customErrors>

</system.web></configuration>

Global.asax

The following example shows the Global.asax file

Security Note:Never set the mode attribute in the customErrors element to "Off" in the Web.config file if you have not created an Application_Error handler in the Global.asax file. If the mode is set to "Off,"

Page 12: Error Handling in ASP

potentially compromising information about your Web site can be exposed to anyone who can cause an error to occur on your site.Visual Basic Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) ' Code that runs when an unhandled error occurs

' Get the exception object. Dim exc As Exception = Server.GetLastError

' Handle HTTP errors (avoid trapping HttpUnhandledException ' which is generated when a non-HTTP exception ' such as the ones generated by buttons 1-3 in ' Default.aspx is not handled at the page level). If (exc.GetType Is GetType(HttpException)) Then ' The Complete Error Handling Example generates ' some errors using URLs with "NoCatch" in them; ' ignore these here to simulate what would happen ' if a global.asax handler were not implemented. If exc.Message.Contains("NoCatch") Then Return End If

'Redirect HTTP errors to HttpError page Server.Transfer("HttpErrorPage.aspx") End If

' For other kinds of errors give the user some information ' but stay on the default page Response.Write("<h2>Global Page Error</h2>" & vbLf) Response.Write("<p>" & exc.Message + "</p>" & vbLf) Response.Write(("Return to the <a href='Default.aspx'>" _ & "Default Page</a>" & vbLf))

' Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage") ExceptionUtility.NotifySystemOps(exc)

' Clear the error from the server Server.ClearError()End Sub

C# void Application_Error(object sender, EventArgs e){ // Code that runs when an unhandled error occurs

// Get the exception object. Exception exc = Server.GetLastError();

// Handle HTTP errors if (exc.GetType() == typeof(HttpException)) { // The Complete Error Handling Example generates // some errors using URLs with "NoCatch" in them; // ignore these here to simulate what would happen // if a global.asax handler were not implemented. if (exc.Message.Contains("NoCatch"))

Page 13: Error Handling in ASP

return;

//Redirect HTTP errors to HttpError page Server.Transfer("HttpErrorPage.aspx"); }

// For other kinds of errors give the user some information // but stay on the default page Response.Write("<h2>Global Page Error</h2>\n"); Response.Write( "<p>" + exc.Message + "</p>\n"); Response.Write("Return to the <a href='Default.aspx'>" + "Default Page</a>\n");

// Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage"); ExceptionUtility.NotifySystemOps(exc);

// Clear the error from the server Server.ClearError();}

ExceptionUtility

The following example shows the ExceptionUtility file. Error logs might be directed to the computer's ErrorLog file, or, if the computer is part of a Web farm, the error log might be recorded in a globally available text file, or even a database. You might also need to immediately notify system administrators of a problem.

The ExceptionUtility class in the example has two static methods: one to log the exception, and one to notify system administrators. How those methods are implemented in your code depends on the needs of your organization. For this example, you must grant write permissions to the ASP.NET worker process account (by default, this is NETWORK SERVICE) for the App_Data folder to enable the application to write to the error log.

Visual Basic Imports SystemImports System.IOImports System.Web

' Create our own utility for exceptionsPublic NotInheritable Class ExceptionUtility

' All methods are static, so this can be private Private Sub New() MyBase.New() End Sub

' Log an Exception Public Shared Sub LogException(ByVal exc As Exception, ByVal source As String) ' Include enterprise logic for logging exceptions ' Get the absolute path to the log file

Page 14: Error Handling in ASP

Dim logFile = "App_Data/ErrorLog.txt" logFile = HttpContext.Current.Server.MapPath(logFile)

' Open the log file for append and write the log Dim sw = New StreamWriter(logFile, True) sw.WriteLine("**** " & DateTime.Now & " ****") If exc.InnerException IsNot Nothing Then sw.Write("Inner Exception Type: ") sw.WriteLine(exc.InnerException.GetType.ToString) sw.Write("Inner Exception: ") sw.WriteLine(exc.InnerException.Message) sw.Write("Inner Source: ") sw.WriteLine(exc.InnerException.Source) If exc.InnerException.StackTrace IsNot Nothing Then sw.WriteLine("Inner Stack Trace: ") sw.WriteLine(exc.InnerException.StackTrace) End If End If sw.Write("Exception Type: ") sw.WriteLine(exc.GetType.ToString) sw.WriteLine("Exception: " & exc.Message) sw.WriteLine("Source: " & source) If exc.StackTrace IsNot Nothing Then sw.WriteLine("Stack Trace: ") sw.WriteLine(exc.StackTrace) End If sw.WriteLine() sw.Close() End Sub

' Notify System Operators about an exception Public Shared Sub NotifySystemOps(ByVal exc As Exception) ' Include code for notifying IT system operators End SubEnd Class

C# using System;using System.IO;using System.Web;

// Create our own utility for exceptionspublic sealed class ExceptionUtility{ // All methods are static, so this can be private private ExceptionUtility() { }

// Log an Exception public static void LogException(Exception exc, string source) { // Include enterprise logic for logging exceptions // Get the absolute path to the log file string logFile = "App_Data/ErrorLog.txt"; logFile = HttpContext.Current.Server.MapPath(logFile);

// Open the log file for append and write the log

Page 15: Error Handling in ASP

StreamWriter sw = new StreamWriter(logFile, true); sw.WriteLine("********** {0} **********", DateTime.Now); if (exc.InnerException != null) { sw.Write("Inner Exception Type: "); sw.WriteLine(exc.InnerException.GetType().ToString()); sw.Write("Inner Exception: "); sw.WriteLine(exc.InnerException.Message); sw.Write("Inner Source: "); sw.WriteLine(exc.InnerException.Source); if (exc.InnerException.StackTrace != null) { sw.WriteLine("Inner Stack Trace: "); sw.WriteLine(exc.InnerException.StackTrace); } } sw.Write("Exception Type: "); sw.WriteLine(exc.GetType().ToString()); sw.WriteLine("Exception: " + exc.Message); sw.WriteLine("Source: " + source); sw.WriteLine("Stack Trace: "); if (exc.StackTrace != null) { sw.WriteLine(exc.StackTrace); sw.WriteLine(); } sw.Close(); }

// Notify System Operators about an exception public static void NotifySystemOps(Exception exc) { // Include code for notifying IT system operators }}

Default.aspx

The following example shows the Default.aspx page. This file provides several buttons, each of which raises a different exception. The Page_Error handler on the page displays an error page and logs some of these errors. Unhandled errors are passed to the Application_Error handler in the Global.asax file. The Application_Error handler displays an error page and logs some of the remaining errors. Any errors that are still not handled are directed to the page indicated by the customErrors section of Web.config file.

Visual Basic <%@ Page Language="VB" %>

<script runat="server"> Protected Sub Submit_Click(ByVal sender As Object, ByVal e As EventArgs) Dim arg As String = CType(sender, Button).CommandArgument Select Case (arg) Case "1" ' Exception handled on the Generic Error Page

Page 16: Error Handling in ASP

Throw New InvalidOperationException("Button 1 was clicked") Exit Select Case "2" ' Exception handled on the current page Throw New ArgumentOutOfRangeException("Button 2 was clicked") Exit Select Case "3" ' Exception handled by Application_Error Throw New Exception("Button 3 was clicked") Exit Select Case "4" ' Exception handled on the Http 404 Error Page Response.Redirect("NonexistentPage.aspx") Exit Select Case "5" ' Exception handled on the Http Error Page Response.Redirect("NonexistentPage-NoCatch.aspx") Exit Select Case "6" ' Exception handled on the Default Redirect Error Page Response.Redirect("Global-NoCatch.asax") Exit Select End Select End Sub

Private Sub Page_Error(ByVal sender As Object, ByVal e As EventArgs) ' Get last error from the server Dim exc As Exception = Server.GetLastError

' Handle exceptions generated by Button 1 If TypeOf exc Is InvalidOperationException Then ' Pass the error on to the Generic Error page Server.Transfer("GenericErrorPage.aspx", True)

' Handle exceptions generated by Button 2 ElseIf TypeOf exc Is ArgumentOutOfRangeException Then ' Give the user some information, but ' stay on the default page Response.Write("<h2>Default Page Error</h2>" & vbLf) Response.Write(("<p>Provide as much information here as is " _ & "appropriate to show to the client.</p>" & vbLf)) Response.Write(("Return to the <a href='Default.aspx'>" _ & "Default Page</a>" & vbLf)) ' Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage") ExceptionUtility.NotifySystemOps(exc) ' Clear the error from the server Server.ClearError() Else ' Pass the error on to the default global handler End If End Sub

</script>

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

Page 17: Error Handling in ASP

<html><head id="Head1" runat="server"> <title>Exception Handler Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Default Page</h2> <p> Click this button to create an InvalidOperationException.<br /> Page_Error will catch this and redirect to GenericErrorPage.aspx.<br /> <asp:Button ID="Submit1" runat="server" CommandArgument="1" OnClick="Submit_Click" Text="Button 1" /> </p> <p> Click this button to create an ArgumentOutOfRangeException.<br /> Page_Error will catch this and handle the error.<br /> <asp:Button ID="Submit2" runat="server" CommandArgument="2" OnClick="Submit_Click" Text="Button 2" /> </p> <p> Click this button to create a generic Exception.<br /> Application_Error will catch this and handle the error.<br /> <asp:Button ID="Submit3" runat="server" CommandArgument="3" OnClick="Submit_Click" Text="Button 3" /> </p> <p> Click this button to create an HTTP 404 (not found) error.<br /> Application_Error will catch this and redirect to HttpErrorPage.aspx.<br /> <asp:Button ID="Submit4" runat="server" CommandArgument="4" OnClick="Submit_Click" Text="Button 4" /> </p> <p> Click this button to create an HTTP 404 (not found) error.<br /> Application_Error will catch this but will not take any action on it, and ASP.NET will redirect to Http404ErrorPage.aspx. The original exception object will not be available.<br /> <asp:Button ID="Submit5" runat="server" CommandArgument="5" OnClick="Submit_Click" Text="Button 5" /> </p> <p> Click this button to create an HTTP 403 (forbidden) error.<br /> Application_Error will catch this but will not take any action on it, and ASP.NET will redirect to DefaultRedirectErrorPage.aspx. The original exception object will not be available.<br /> <asp:Button ID="Button1" runat="server" CommandArgument="6" OnClick="Submit_Click" Text="Button 6" /> </p>

Page 18: Error Handling in ASP

</div> </form></body></html>

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

<script runat="server"> protected void Submit_Click(object sender, EventArgs e) { string arg = ((Button)sender).CommandArgument;

switch (arg) { case "1": { // Exception handled on the Generic Error Page throw new InvalidOperationException("Button 1 was clicked"); break; } case "2": { // Exception handled on the current page throw new ArgumentOutOfRangeException("Button 2 was clicked"); break; } case "3": { // Exception handled by Application_Error throw new Exception("Button 3 was clicked"); break; } case "4": { // Exception handled on the Http 404 Error Page Response.Redirect("NonexistentPage.aspx"); break; } case "5": { // Exception handled on the Http Error Page Response.Redirect("NonexistentPage-NoCatch.aspx"); break; } case "6": { // Exception handled on the Generic Http Error Page Response.Redirect("Global-NoCatch.asax"); break; } } } private void Page_Error(object sender, EventArgs e) { // Get last error from the server Exception exc = Server.GetLastError();

Page 19: Error Handling in ASP

// Handle exceptions generated by Button 1 if (exc is InvalidOperationException) { // Pass the error on to the Generic Error page Server.Transfer("GenericErrorPage.aspx", true); }

// Handle exceptions generated by Button 2 else if (exc is ArgumentOutOfRangeException) { // Give the user some information, but // stay on the default page Response.Write("<h2>Default Page Error</h2>\n"); Response.Write("<p>Provide as much information here as is " + "appropriate to show to the client.</p>\n"); Response.Write("Return to the <a href='Default.aspx'>" + "Default Page</a>\n");

// Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage"); ExceptionUtility.NotifySystemOps(exc);

// Clear the error from the server Server.ClearError(); } else { // Pass the error on to the default global handler } }</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>Exception Handler Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Default Page</h2> <p> Click this button to create an InvalidOperationException.<br /> Page_Error will catch this and redirect to GenericErrorPage.aspx.<br /> <asp:Button ID="Submit1" runat="server" CommandArgument="1" OnClick="Submit_Click" Text="Button 1" /> </p> <p> Click this button to create an ArgumentOutOfRangeException.<br /> Page_Error will catch this and handle the error.<br /> <asp:Button ID="Submit2" runat="server" CommandArgument="2" OnClick="Submit_Click"

Page 20: Error Handling in ASP

Text="Button 2" /> </p> <p> Click this button to create a generic Exception.<br /> Application_Error will catch this and handle the error.<br /> <asp:Button ID="Submit3" runat="server" CommandArgument="3" OnClick="Submit_Click" Text="Button 3" /> </p> <p> Click this button to create an HTTP 404 (not found) error.<br /> Application_Error will catch this and redirect to HttpErrorPage.aspx.<br /> <asp:Button ID="Submit4" runat="server" CommandArgument="4" OnClick="Submit_Click" Text="Button 4" /> </p> <p> Click this button to create an HTTP 404 (not found) error.<br /> Application_Error will catch this but will not take any action on it, and ASP.NET will redirect to Http404ErrorPage.aspx. The original exception object will not be available.<br /> <asp:Button ID="Submit5" runat="server" CommandArgument="5" OnClick="Submit_Click" Text="Button 5" /> </p> <p> Click this button to create an HTTP 403 (forbidden) error.<br /> Application_Error will catch this but will not take any action on it, and ASP.NET will redirect to DefaultRedirectErrorPage.aspx. The original exception object will not be available.<br /> <asp:Button ID="Button1" runat="server" CommandArgument="6" OnClick="Submit_Click" Text="Button 6" /> </p> </div> </form></body></html>

GenericErrorPage.aspx

The following example shows the GenericErrorPage.aspx page. This page creates a safe message that it displays to remote users. For local users (typically developers and testers of the application), the page displays a complete exception report. The Page_Error handler redirects InvalidOperationException errors to this page.

Visual Basic <%@ Page Language="VB" %>

Page 21: Error Handling in ASP

<script runat="server"> Dim ex As Exception = Nothing

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) ' Get the last error from the server Dim ex As Exception = Server.GetLastError

' Create a safe message Dim safeMsg = "A problem has occurred in the web site. "

' Show Inner Exception fields for local access If ex.InnerException IsNot Nothing Then innerTrace.Text = ex.InnerException.StackTrace InnerErrorPanel.Visible = Request.IsLocal innerMessage.Text = ex.InnerException.Message End If

' Show Trace for local access If Request.IsLocal Then exTrace.Visible = True Else ex = New Exception(safeMsg, ex) End If

' Fill the page fields exMessage.Text = ex.Message exTrace.Text = ex.StackTrace

' Log the exception and notify system operators ExceptionUtility.LogException(ex, "Generic Error Page") ExceptionUtility.NotifySystemOps(ex)

' Clear the error from the server Server.ClearError() End Sub

</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>Generic Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Generic Error Page</h2> <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false"> <p> Inner Error Message:<br /> <asp:Label ID="innerMessage" runat="server" Font-Bold="true" Font-Size="Large" /><br /> </p> <pre> <asp:Label ID="innerTrace" runat="server" />

Page 22: Error Handling in ASP

</pre> </asp:Panel> <p> Error Message:<br /> <asp:Label ID="exMessage" runat="server" Font-Bold="true" Font-Size="Large" /> </p> <pre> <asp:Label ID="exTrace" runat="server" Visible="false" /> </pre> <br /> Return to the <a href='Default.aspx'>Default Page</a> </div> </form></body></html>

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

<script runat="server"> protected Exception ex = null;

protected void Page_Load(object sender, EventArgs e) { // Get the last error from the server Exception ex = Server.GetLastError();

// Create a safe message string safeMsg = "A problem has occurred in the web site. ";

// Show Inner Exception fields for local access if (ex.InnerException != null) { innerTrace.Text = ex.InnerException.StackTrace; InnerErrorPanel.Visible = Request.IsLocal; innerMessage.Text = ex.InnerException.Message; } // Show Trace for local access if (Request.IsLocal) exTrace.Visible = true; else ex = new Exception(safeMsg, ex);

// Fill the page fields exMessage.Text = ex.Message; exTrace.Text = ex.StackTrace;

// Log the exception and notify system operators ExceptionUtility.LogException(ex, "Generic Error Page"); ExceptionUtility.NotifySystemOps(ex);

// Clear the error from the server Server.ClearError(); }</script>

Page 23: Error Handling in ASP

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>Generic Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Generic Error Page</h2> <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false"> <p> Inner Error Message:<br /> <asp:Label ID="innerMessage" runat="server" Font-Bold="true" Font-Size="Large" /><br /> </p> <pre> <asp:Label ID="innerTrace" runat="server" /> </pre> </asp:Panel> <p> Error Message:<br /> <asp:Label ID="exMessage" runat="server" Font-Bold="true" Font-Size="Large" /> </p> <pre> <asp:Label ID="exTrace" runat="server" Visible="false" /> </pre> <br /> Return to the <a href='Default.aspx'> Default Page</a> </div> </form></body></html>

HttpErrorPage.aspx

The following example shows the HttpErrorPage.aspx page. This page also creates a safe message that depends on the value of the error code, which it displays to remote users. For local users, the page displays a complete exception report. The Application_Error handler redirects HttpException errors to this page.

Visual Basic <%@ Page Language="VB" %>

<script runat="server"> Dim ex As HttpException = Nothing

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) ex = CType(Server.GetLastError, HttpException) Dim httpCode As Integer = ex.GetHttpCode

' Filter for Error Codes and set text

Page 24: Error Handling in ASP

If ((httpCode >= 400) AndAlso (httpCode < 500)) Then ex = New HttpException(httpCode, _ "Safe message for 4xx HTTP codes.", ex) ElseIf (httpCode > 499) Then ex = New HttpException(ex.ErrorCode, _ "Safe message for 5xx HTTP codes.", ex) Else ex = New HttpException(httpCode, _ "Safe message for unexpected HTTP codes.", ex) End If

' Log the exception and notify system operators ExceptionUtility.LogException(ex, "HttpErrorPage") ExceptionUtility.NotifySystemOps(ex)

' Fill the page fields exMessage.Text = ex.Message exTrace.Text = ex.StackTrace

' Show Inner Exception fields for local access If ex.InnerException IsNot Nothing Then innerTrace.Text = ex.InnerException.StackTrace InnerErrorPanel.Visible = Request.IsLocal innerMessage.Text = _ "HTTP " & httpCode & ": " & ex.InnerException.Message End If

' Show Trace for local access exTrace.Visible = Request.IsLocal ' Clear the error from the server Server.ClearError() End Sub

</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>Http Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Http Error Page</h2> <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false"> <asp:Label ID="innerMessage" runat="server" Font-Bold="true" Font-Size="Large" /><br /> <pre> <asp:Label ID="innerTrace" runat="server" /> </pre> </asp:Panel> Error Message:<br /> <asp:Label ID="exMessage" runat="server" Font-Bold="true" Font-Size="Large" /> <pre>

Page 25: Error Handling in ASP

<asp:Label ID="exTrace" runat="server" Visible="false" /> </pre> <br /> Return to the <a href='Default.aspx'>Default Page</a> </div> </form></body></html>

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

<script runat="server"> protected HttpException ex = null;

protected void Page_Load(object sender, EventArgs e) { ex = (HttpException)Server.GetLastError(); int httpCode = ex.GetHttpCode();

// Filter for Error Codes and set text if (httpCode >= 400 && httpCode < 500) ex = new HttpException (httpCode, "Safe message for 4xx HTTP codes.", ex); else if (httpCode > 499) ex = new HttpException (ex.ErrorCode, "Safe message for 5xx HTTP codes.", ex); else ex = new HttpException (httpCode, "Safe message for unexpected HTTP codes.", ex);

// Log the exception and notify system operators ExceptionUtility.LogException(ex, "HttpErrorPage"); ExceptionUtility.NotifySystemOps(ex);

// Fill the page fields exMessage.Text = ex.Message; exTrace.Text = ex.StackTrace;

// Show Inner Exception fields for local access if (ex.InnerException != null) { innerTrace.Text = ex.InnerException.StackTrace; InnerErrorPanel.Visible = Request.IsLocal; innerMessage.Text = string.Format("HTTP {0}: {1}", httpCode, ex.InnerException.Message); } // Show Trace for local access exTrace.Visible = Request.IsLocal;

// Clear the error from the server Server.ClearError(); }</script>

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

Page 26: Error Handling in ASP

<html><head id="Head1" runat="server"> <title>Http Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> Http Error Page</h2> <asp:Panel ID="InnerErrorPanel" runat="server" Visible="false"> <asp:Label ID="innerMessage" runat="server" Font-Bold="true" Font-Size="Large" /><br /> <pre> <asp:Label ID="innerTrace" runat="server" /> </pre> </asp:Panel> Error Message:<br /> <asp:Label ID="exMessage" runat="server" Font-Bold="true" Font-Size="Large" /> <pre> <asp:Label ID="exTrace" runat="server" Visible="false" /> </pre> <br /> Return to the <a href='Default.aspx'>Default Page</a> </div> </form></body></html>

Http404ErrorPage.aspx

The following example shows the Http404ErrorPage.aspx page. ASP.NET redirects unhandled HTTP 404 (file not found) errors to this page. The page displays the same message to remote and local users.

Visual Basic <%@ Page Language="VB" %>

<script runat="server"> Dim ex As HttpException

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) ' Log the exception and notify system operators ex = New HttpException("defaultRedirect") ExceptionUtility.LogException(ex, "Caught in DefaultRedirectErrorPage") ExceptionUtility.NotifySystemOps(ex) End Sub

</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>HTTP 404 Error Page</title>

Page 27: Error Handling in ASP

</head><body> <form id="form1" runat="server"> <div> <h2> HTTP 404 Error Page</h2> Standard error message suitable for file not found errors. The original exception object is not available, but the original requested URL is in the query string.<br /> <br /> Return to the <a href='Default.aspx'> Default Page</a> </div> </form></body></html>

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

<script runat="server"> protected HttpException ex = null;

protected void Page_Load(object sender, EventArgs e) { // Log the exception and notify system operators ex = new HttpException("HTTP 404"); ExceptionUtility.LogException(ex, "Caught in Http404ErrorPage"); ExceptionUtility.NotifySystemOps(ex); }</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>HTTP 404 Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> HTTP 404 Error Page</h2> Standard error message suitable for file not found errors. The original exception object is not available, but the original requested URL is in the query string.<br /> <br /> Return to the <a href='Default.aspx'> Default Page</a> </div> </form></body></html>

DefaultRedirectErrorPage.aspx

Page 28: Error Handling in ASP

The following example shows the DefaultRedirectErrorPage.aspx page. ASP.NET redirects any unhandled errors except HTTP 404 errors to this page. The page displays the same message to remote and local users.

Visual Basic <%@ Page Language="VB" %>

<script runat="server"> Dim ex As HttpException

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) ' Log the exception and notify system operators ex = New HttpException("defaultRedirect") ExceptionUtility.LogException(ex, "Caught in DefaultRedirectErrorPage") ExceptionUtility.NotifySystemOps(ex) End Sub

</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head id="Head1" runat="server"> <title>DefaultRedirect Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> DefaultRedirect Error Page</h2> Standard error message suitable for all unhandled errors. The original exception object is not available.<br /> <br /> Return to the <a href='Default.aspx'>Default Page</a> </div> </form></body></html>

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

<script runat="server"> protected HttpException ex = null;

protected void Page_Load(object sender, EventArgs e) { // Log the exception and notify system operators ex = new HttpException("defaultRedirect"); ExceptionUtility.LogException(ex, "Caught in DefaultRedirectErrorPage"); ExceptionUtility.NotifySystemOps(ex); }</script>

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

Page 29: Error Handling in ASP

<html><head id="Head1" runat="server"> <title>DefaultRedirect Error Page</title></head><body> <form id="form1" runat="server"> <div> <h2> DefaultRedirect Error Page</h2> Standard error message suitable for all unhandled errors. The original exception object is not available.<br /> <br /> Return to the <a href='Default.aspx'> Default Page</a> </div> </form></body></html>

ASP.NETHow to: Handle Application-Level Errors

Updated: April 2009

This code example shows how to create an error handler in the Global.asax file that will catch all unhandled ASP.NET errors while processing a request — in other words, all the errors that are not caught with a Try/Catch block or in a page-level error handler. In the example, the handler transfers control to a generic error page named GenericErrorPage.aspx, which interprets the error and displays an appropriate message.

 Example

The following example is from a complete code sample in Complete Example for Error Handlers.

Security Note:Never set customErrors to Off in your Web.config file if you do not have an Application_Error handler in your Global.asax file. Potentially compromising information about your Web site can be exposed to anyone who can cause an error to occur on your site.Visual Basic Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs) ' Code that runs when an unhandled error occurs

' Get the exception object. Dim exc As Exception = Server.GetLastError

' Handle HTTP errors (avoid trapping HttpUnhandledException ' which is generated when a non-HTTP exception ' such as the ones generated by buttons 1-3 in

Page 30: Error Handling in ASP

' Default.aspx is not handled at the page level). If (exc.GetType Is GetType(HttpException)) Then ' The Complete Error Handling Example generates ' some errors using URLs with "NoCatch" in them; ' ignore these here to simulate what would happen ' if a global.asax handler were not implemented. If exc.Message.Contains("NoCatch") Then Return End If

'Redirect HTTP errors to HttpError page Server.Transfer("HttpErrorPage.aspx") End If

' For other kinds of errors give the user some information ' but stay on the default page Response.Write("<h2>Global Page Error</h2>" & vbLf) Response.Write("<p>" & exc.Message + "</p>" & vbLf) Response.Write(("Return to the <a href='Default.aspx'>" _ & "Default Page</a>" & vbLf))

' Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage") ExceptionUtility.NotifySystemOps(exc)

' Clear the error from the server Server.ClearError()End Sub

C# void Application_Error(object sender, EventArgs e){ // Code that runs when an unhandled error occurs

// Get the exception object. Exception exc = Server.GetLastError();

// Handle HTTP errors if (exc.GetType() == typeof(HttpException)) { // The Complete Error Handling Example generates // some errors using URLs with "NoCatch" in them; // ignore these here to simulate what would happen // if a global.asax handler were not implemented. if (exc.Message.Contains("NoCatch")) return;

//Redirect HTTP errors to HttpError page Server.Transfer("HttpErrorPage.aspx"); }

// For other kinds of errors give the user some information // but stay on the default page Response.Write("<h2>Global Page Error</h2>\n"); Response.Write( "<p>" + exc.Message + "</p>\n"); Response.Write("Return to the <a href='Default.aspx'>" +

Page 31: Error Handling in ASP

"Default Page</a>\n");

// Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage"); ExceptionUtility.NotifySystemOps(exc);

// Clear the error from the server Server.ClearError();}

 Robust Programming

An error handler that is defined in the Global.asax file will only catch errors that occur during processing of requests by the ASP.NET runtime. For example, it will catch the error if a user requests an .aspx file that does not occur in your application. However, it does not catch the error if a user requests a nonexistent .htm file. For non-ASP.NET errors, you can create a custom handler in Internet Information Services (IIS). The custom handler will also not be called for server-level errors.

You cannot directly output error information for requests from the Global.asax file; you must transfer control to another page, typically a Web Forms page. When transferring control to another page, use Transfer method. This preserves the current context so that you can get error information from the GetLastError method.

After handling an error, you must clear it by calling the ClearError method of the Server object (HttpServerUtility class).

 Security

Be sure that you do not display error information that might help malicious users compromise your application. For details, see How to: Display Safe Error Messages.

ASP.NETHow to: Handle Page-Level Errors

If possible, you should handle errors in Try/Catch blocks within your code, because a problem is more easily corrected where it occurs. If the user can help correct a problem, the page needs to return to the same place so the user has a context for understanding what to do.

A page-level handler returns you to the page, but there is no longer anything on the page because instances of controls are not created. To provide the user any information, you must specifically write it to the page.

You would probably use a page-level error handler to log unhandled errors or to take the user to a page that can display helpful information.

Page 32: Error Handling in ASP

This code example shows a handler for the Error event in an ASP.NET Web page. This handler catches all exceptions that are not already handled within Try/Catch blocks in the page.

After you handle an error, you must clear it by calling the ClearError method of the Server object (HttpServerUtility class).

 Example

This handler filters for specific kinds of exceptions. For an ArgumentOutOfRangeException exception, the handler writes some text on the page, provides a link back to the page, logs the error, and notifies system administrators. For an InvalidOperationException exception, the handler simply transfers the exception to the Generic Error Page. For any other kind of exception, the handler does nothing, which allows your site to automatically redirect to the generic page specified in the Web.config file. Your own code would filter for exceptions that are important to your application.

The following example is part of a complete code sample in Complete Example for Error Handlers

Visual Basic Private Sub Page_Error(ByVal sender As Object, ByVal e As EventArgs) ' Get last error from the server Dim exc As Exception = Server.GetLastError

' Handle exceptions generated by Button 1 If TypeOf exc Is InvalidOperationException Then ' Pass the error on to the Generic Error page Server.Transfer("GenericErrorPage.aspx", True)

' Handle exceptions generated by Button 2 ElseIf TypeOf exc Is ArgumentOutOfRangeException Then ' Give the user some information, but ' stay on the default page Response.Write("<h2>Default Page Error</h2>" & vbLf) Response.Write(("<p>Provide as much information here as is " _ & "appropriate to show to the client.</p>" & vbLf)) Response.Write(("Return to the <a href='Default.aspx'>" _ & "Default Page</a>" & vbLf)) ' Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage") ExceptionUtility.NotifySystemOps(exc) ' Clear the error from the server Server.ClearError() Else ' Pass the error on to the default global handler End IfEnd Sub

C# private void Page_Error(object sender, EventArgs e){ // Get last error from the server Exception exc = Server.GetLastError();

Page 33: Error Handling in ASP

// Handle exceptions generated by Button 1 if (exc is InvalidOperationException) { // Pass the error on to the Generic Error page Server.Transfer("GenericErrorPage.aspx", true); }

// Handle exceptions generated by Button 2 else if (exc is ArgumentOutOfRangeException) { // Give the user some information, but // stay on the default page Response.Write("<h2>Default Page Error</h2>\n"); Response.Write("<p>Provide as much information here as is " + "appropriate to show to the client.</p>\n"); Response.Write("Return to the <a href='Default.aspx'>" + "Default Page</a>\n");

// Log the exception and notify system operators ExceptionUtility.LogException(exc, "DefaultPage"); ExceptionUtility.NotifySystemOps(exc);

// Clear the error from the server Server.ClearError(); } else { // Pass the error on to the default global handler }}

ASP.NETASP.NET Debugging

Application code can contain various types of errors, or bugs. Most syntax errors are caught during compilation. However, other types of errors require that you debug your code — that is, that you examine the code while it is running to validate that the execution path and data is as it should be.

The topics in this section provide information about how to use the debugger in the Windows Software Development Kit (SDK) to help you find errors in ASP.NET Web pages.

 In This Section ASP.NET Debugging OverviewUsing the Debugger with Web PagesWhat's New in the Visual Studio DebuggerHow to: Set Up Remote DebuggingDebugging ASP.NET and AJAX Applications

Page 34: Error Handling in ASP

ASP.NETASP.NET Debugging Overview

Application code can contain various types of errors, or bugs. Most syntax errors are caught during compilation. However, other types of errors require that you debug your code — that is, that you examine the code while it is running to validate that the execution path and data is as it should be.

This topic provides information about how to use the debugger in the Windows Software Development Kit (SDK) to help you find errors in ASP.NET Web pages.

 Background

Application code can contain various types of errors, or bugs. Most syntax errors are caught during compilation. However, other types of errors require that you debug your code — that is, that you examine the code while it is running to validate that the execution path and data is as it should be. For more information, see Debugging and Profiling Applications.

The Windows Software Development Kit (SDK) includes a tool called Visual Debugger that allows you to examine an application while it is running. This tool is located in %ProgramFiles%\Microsoft Visual Studio 8\SDK\v2.0\GuiDebug\DbgCLR.exe. Using the debugger, you can see exactly how your application is working by stepping through each statement as it executes and by viewing the data in each variable. To use Visual Debugger, open it and then attach it to the process that is running the pages of your ASP.NET application. In Internet Information Services (IIS) versions 5.0 and 5.1, and in IIS 6.0 running in IIS 5.0 application mode, the process to which you attach the debugger is the ASP.NET worker process (Aspnet_wp.exe). In IIS 6.0 running in worker process isolation mode, the process that you attach to is the thread pool process (W3wp.exe). When the debugger is attached to a process, you can view everything going on during that process, and the debugger maps the instructions being executed in the process back to your original code so that you can see each line of code being executed.

Visual Debugger

Visual Debugger allows you to examine code while it is running and includes features that help you debug applications, including the following:

Breakpoints   Breakpoints are places in the code where the debugger will stop the application, allow you to view the current data state of the application, and then step through each line of code. For information, see Debugging Basics: Breakpoints.

Stepping   Once you have stopped at a breakpoint, you can run the code line by line (known as stepping through the code). Visual Debugger includes a number of features to help you step through your code, such as iterators that allow you to specify how many times to step through a loop before stopping again. For more information, see Code Stepping Overview.

Page 35: Error Handling in ASP

Data Viewing   Visual Debugger gives you many different options for viewing and tracking data while the application is running. The debugger allows you to modify the data while the application is stopped in break mode and then continue to run the application with the modified data. For more information, see Viewing Data in the Debugger.

Note:The Edit and Continue feature of Visual Studio 2005 is not available for Web applications.

For more information, see Using the Debugger with Web Pages.

Configuring ASP.NET Web Applications for Debugging

To enable debugging for an ASP.NET Web application, you must configure the application to compile into a debug build. A debug build includes information that the debugger needs so that it can step through your code and display the contents of variables. You configure your Web application for debug builds in the Compilation section of your application's Web.config file. For more information, see compilation Element (ASP.NET Settings Schema). Alternatively, if you want to debug only single pages, you can add debug=true to the @ Page directive on the pages that you wish to debug. For more information, see How to: Enable Debugging for ASP.NET Applications.

Note:An application compiled into a debug build will perform considerably more slowly than if it is compiled into a retail build. Be sure you have debug mode turned off before you deploy your application. Additionally, in debug mode, more information is exposed in the stack when an error occurs and can be a potential security issue.

Local and Remote Debugging

If you are running a Web server locally, such as IIS, you can debug applications running locally on your computer so that you can view your pages in a browser.

If you cannot run a page locally, because you cannot run a Web server or because the application is not available to you locally, you can debug an application running on another server. In order to debug remotely, you must install the Visual Studio remote debugging components on the remote server. For more information, see How to: Set Up Remote Debugging.

Permissions for Debugging

Debugging a process requires more privileges than running it. Therefore, in addition to configuring your application for debugging, you must also ensure that you have adequate permissions to attach to a process in order to debug it. Users have the permission to debug processes running under their own user local identity, but they cannot debug other user's processes. Administrators can debug any process.

Page 36: Error Handling in ASP

To debug on a remote server, you need administrator privileges on the computer where the process to be debugged runs. For more information, see How to: Debug Web Applications on a Remote Server.

Client-Side Script Debugging

In addition to server-side application debugging, Visual Debugger allows you to debug client script written in ECMAScript (JavaScript) or VBScript. Client-script debugging can be especially useful when you have Web server controls that use client-side script.

Visual Web DeveloperDebugging Web Pages Overview

The ASP.NET page framework provides extensive support for debugging Web applications. However, because Web applications are distributed, there are some special issues associated with debugging them.

In general, you debug Web applications the same way you do other types of Visual Studio applications. You can set breakpoints, start the debugger, break into code, examine variables, and perform all the functions associated with the Visual Studio debugger. For details, see Debugger Roadmap. In addition, the ASP.NET page framework provides a trace mode that enables you to insert instrumentation messages into your forms. For details, see Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors and Walkthrough: Integrating ASP.NET Tracing with System.Diagnostics Tracing.

 Debugger Configuration

Web application debugging requires certain components on the computer where debugging is to happen and requires that you have adequate permissions.

Local Computer Configuration

If you are running Web applications locally on your computer—that is, the Web server is on your computer—then the computer has the correct components automatically.

You must still make sure that you have adequate permissions to debug. Users have the permission to debug processes running under their user identity, but cannot debug other user's processes. Administrators can debug any process.

Remote Computer Configuration

If the Web server is on another computer (a remote server), you must ensure that the computer is configured properly. This involves:

Page 37: Error Handling in ASP

Making sure that DCOM is installed on both your computer and on the server. Windows 2000 and Windows Server 2003 normally have DCOM installed already, so there is usually no action required on your part.

Installing Visual Studio server-side components on the remote computer. You can do this by running the Visual Studio installation process on the remote computer and selecting the option for server components.

Ensuring that any debugger users have permissions to attach to a Web server process. This means that server processes must either run as the user (impersonation) or that users who want to debug must have administrative privileges on the Web server. (Giving users administrative privileges on the server might not be in keeping with your security policies.) You can control ASP.NET impersonation using the identity element of the Web.config file for your application. For details, see <identity> Element.

For details about configuring for remote debugging, see Debugging Web Applications on a Remote Server.

Whether you are running locally or on a remote computer, you must be sure that debugging is enabled for your Web application specifically. This is done in the compilation Element (ASP.NET Settings Schema) element of the Web.config file that is part of your Web application project. This setting instructs the compiler to insert debugging symbols into the application's compiled code so that you can use the debugger with it. You can enable debugging using the Web Site Administration Tool. For details, see Walkthrough: Debugging Web Pages in Visual Web Developer.

 Debugging Client Script

Client script runs within the browser, separately from the code in your Web application, which runs on the server. You can use the Visual Studio debugger to debug client script. The debugger does not enable you to follow execution from server code to client script; however, it does support most other debugging functionality for client script.

You can debug client script in various ways. From within Visual Studio, you can use debugger commands to attach to the browser process (Iexplore.exe) and break into the script. From there, you can use the debugger as you would for any other code.

Page 38: Error Handling in ASP

Error Handling in ASP.NET

Introduction

When errors occur in an ASP.NET application, they either get handled or propagates unhandled to higher scopes. When an unhandled exception propagates, the user may be redirected to an error page using different ASP.NET configuration settings. However, such a redirection may be prevented in the first place by handling the exceptions that get thrown. Error handling in ASP.NET therefore, may be divided into two separate logics:

Redirecting the user to an error page when errors go unhandled. Handling exceptions when they get thrown.

Redirecting the user to an error page

There are two different scopes where we could specify which page the user should be redirected to, when errors go unhandled:

Page level (applies to errors that happen within a single page). Application level (applies to errors that happen anywhere in the application).

Page Level

Page 39: Error Handling in ASP

Use the errorPage attribute in the webform.

This attribute defines the page the user should be redirected to when an unhandled exception occurs in that specific page. For example,

Collapse

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebTest.WebForm1" errorPage="/WebTest/ErrorPages/PageError.html"%>

The errorPage attribute maps to the Page.ErrorPage property, and hence may be set programmatically. The value may optionally include query string parameters. If no parameters are added, ASP.NET would automatically add one with the name aspxerrorpath. This parameter would hold the value of the relative URL to this page, so that the error page would be able to determine which page caused the error.

If a value is specified in this attribute (or property) and an unhandled exception occurs in the page, the Page class would automatically perform a redirect to the specified page. If a value is not specified, the exception is assumed to be unhandled, wrapped in a new HttpUnhandledException and then thrown, propagating it to the next higher level.

Application Level

Use the customErrors section in web.config.

This section lets you specify the error page to which the user should be redirected to when an unhandled exception propagates in the application level. This section specifies error pages for both default errors as well as the HTTP status code errors.

Collapse

<customErrors mode="On" defaultRedirect="/WebTest/ErrorPages/AppError.html"> <error statusCode="404" redirect="/WebTest/ErrorPages/404.html" /></customErrors>

The mode attribute specifies whether to show user-defined custom error pages or ASP.NET error pages. Three values are supported for this attribute:

RemoteOnly - Custom error pages are shown for all remote users. ASP.NET error pages with rich error information are displayed only for local users.

On - Custom error pages are always shown, unless one is not specified. When a custom error page is not defined, an ASP.NET error page will be displayed which describes how to enable remote viewing of errors.

Off - Custom error pages are not shown. Instead, ASP.NET error pages will be displayed always, which will have rich error information.

Page 40: Error Handling in ASP

It's a bad idea to give users more information than what is required. ASP.NET error pages describe technical details that shouldn't be exposed. Ideally, the mode attribute thus should not be set to Off.

The defaultRedirect attribute specifies the path to a generic error page. This page would typically have a link to let the user go back to the home page or perform the request once again.

Each error element defines a redirect specific to a particular HTTP status code. For example, if the error is a 404 (File Not Found), then you could set the error page as FileNotFound.htm. You could add as many error elements in the customErrors section as required, each of which specifies a status code and the corresponding error page path. If ASP.NET can�t find any specific error element corresponding to a status code, it would use the value specified in the defaultRedirect attribute.

Notes The settings specified in the page level (errorPage attribute) would override those specified in

the customErrors section. The reason is because errors in the page would be handled by the Page class first, which might thus prevent the exception from being propagated to the application level. It�s only when the Page class fails to handle the exception that the values set in customErrors come into scope.

All these settings mentioned above apply only for requests that are made for ASP.NET files. More specifically, these settings would work only for requests for files with extensions that are mapped to the aspnet_isapi. For example, if you request for an ASP or JPG file (extensions that are not mapped to aspnet_isapi) which does not exist, then these settings won�t work, and the standard error page specified in IIS would be displayed. To modify this behavior, either map the required extensions to aspnet_isapi or modify the custom error pages specified in IIS.

Handling exceptions

There are different levels where you could handle exceptions.

Locally (method level), where exceptions could be thrown. Page level by handling the Page.Error event.

Application level by handling the HttpApplication.Error event.

HTTP Module level by handling the HttpApplication.Error event.

Local error handling

Wrap code that might throw exceptions in a try-catch-finally block.

If you can recover from the exception, then handle it in the catch block. If the exception cannot be recovered from locally, let the exception propagate to higher levels by throwing it. If the exception cannot be recovered from locally, but additional information can be provided, then

Page 41: Error Handling in ASP

wrap the exception with the new information and throw the new exception. This method is used when you use custom exceptions. Place the clean up code in the finally block.

Find more information on exception handling best practices available in MSDN.

Note: The more exceptions you catch and throw, the slower your application would run. This is more significant in web applications.

Page Level

Attach a handler to the Page.Error event. In C#, you will have to write the event wire up code yourself in the Page_Load method.

When an exception goes unhandled in a page, the Error event of the Page class gets triggered.

Typically, the first action you would perform in this handler would be to obtain the exception thrown, by using the Server.GetLastError method. This method would return a reference to the last Exception object that was thrown.

After you get the Exception object, you will want to redirect the user to an error page. We could make ASP.NET do the redirection by using the errorPage attribute of the Page (design time) or by using the Page.ErrorPage property (runtime). Obviously, the choice here would be to programmatically set the value using the Page.ErrorPage property in the event handler.

Collapse

private void WebForm1_Error(object sender, EventArgs e){ // Get the last exception thrown

Exception ex = Server.GetLastError();

// Do something with the exception like logging etc.

// Set the error page

this.ErrorPage = "/ErrorHandling/ErrorPages/BaseError.html";}

If you do not specify an error page, the exception gets wrapped inside an HttpUnhandledException object and propagates. If you don�t want the exception to be wrapped, then simply throw the last exception, which would force immediate propagation escaping any intervention. However, this would prevent ASP.NET from redirecting the user to a page specific page either. In other words, if you are going to throw the last error (or any exception for that matter), setting the error page will have no effect.

Collapse

Page 42: Error Handling in ASP

private void BasePage_Error(object sender, EventArgs e){ // Get the last exception thrown

Exception ex = Server.GetLastError();

// Do something with the exception like logging etc.

// The statement below has no significance - it's as good as commented

this.ErrorPage = "/ErrorHandling/ErrorPages/BaseError.html";

// Throw the error to prevent wrapping

throw ex;}

To reduce redundant code, you could define a base web form page which defines the Page.Error event handler and then wire up code in the constructor, and then make all your Web Form pages derive from this base page. This would save you the effort of writing the error handler in each web form.

Application Level

Attach an event handler to the Application.Error event.

When an unhandled exception leaves a page, it gets propagated to the application level, which would trigger this event.

There are two things you would want to do in an application error handler.

Get the last exception thrown using Server.GetLastError. Clear the error using Server.ClearError, to inform ASP.NET that you have handled the error.

If you don�t clear the error, the exception would propagate. However, since there isn't any higher scope where the exception could be caught, ASP.NET is forced to handle it. The way ASP.NET handles the exception depends upon the settings specified in the customErrors section we saw before. If no settings are defined, ASP.NET would use the defaults and display the infamous 'yellow' error page.

HTTP Module Level

Instead of handling application errors in global.asax, exceptions may also be handled by attaching an HTTP Module which would have a handler attached to the Application.Error event. This method would be triggered before the corresponding application handler would be invoked. Such an implementation would be beneficial if you have multiple projects with the same global error handling implementation. In such a scenario, you could create a module and attach it to each web application you have.

Page 43: Error Handling in ASP

All the points we saw in the Page and Application handlers apply to the Module handler as well.

Important Notes

Prevent infinite recursion

If an error occurs in the error handling code, an infinite recursive loop would result, which would soon drag your server down. The reason why this happens is because the new exception would trigger the error event once again which would in turn redirect control to the handler, which would cause yet another exception to be thrown, making an infinite loop.

This might also happen if the error page itself throws an exception. To counter this possibility, making error pages static is a good idea.

Errors may also happen while attempting to redirect to an error page using Server.Transfer or Response.Redirect maybe due to an invalid path. To tackle this scenario, we could wrap the redirection code in a try-catch block. If the redirection fails, then we have nothing more to do other than setting the response code and completing the response, using the Response.StatusCode property and the HttpApplication.CompleteResponse method. This would then be handled by the settings specified in the customErrors section.

Parser Errors

Parser errors are caused due to invalid tags (or similar reasons) in an aspx page. These errors are usually of type HttpParseException. Such errors will not be caught by the Page level handler as page parsing happens before ASP.NET creates the assembly for the aspx page. In other words, parser errors are thrown while ASP.NET reads the aspx file and tries to create its assembly, and hence is way before the corresponding type is created. Thus, such errors will have to be handled in the application scope.

Exception logging and response time

Users need to get responses as quick as possible. Implementation wise, this means that when errors happen, error recovery processes should be quick and users should be redirected or informed of the error as soon as possible. If exceptions are going to be logged to a file or other mediums, then it could take time which would lead to a slow response. Making exception logging an asynchronous process would be a good idea in this respect.

ASP.NETUsing the Debugger with Web Pages

The topics in this section provide details about how to use debugger features to examine running code in an ASP.NET application.

Page 44: Error Handling in ASP

 In This Section Attaching to Running ProcessesDebugging Basics: BreakpointsExecution ControlViewing Data in the Debugger

Visual Studio DebuggerAttaching to Running Processes

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

The Visual Studio debugger has the ability to attach to a process that is running outside of Visual Studio. You can use this attach capability to do the following:

Debug an application that was not created in Visual Studio. Debug multiple processes simultaneously. You can also debug multiple processes by

starting multiple projects within a single solution.

Debug a process running on a remote computer.

Debug a DLL that runs in a separate process that cannot easily be started from Visual Studio, for example, a service or an ISAPI DLL running with Internet Information Services.

Start the debugger automatically when a process crashes while running outside of Visual Studio. This is Just-In-Time debugging.

After you have attached to a program, you can use debugger execution commands, inspect the program state, and so on. For more information, see Execution Control and Viewing Data in the Debugger. Your ability to inspect the program may be limited, of course, depending on whether the program was built with debug information and whether you have access to the program's source code, and whether the common language runtime JIT compiler is tracking debug information.

Note:

Page 45: Error Handling in ASP

For the debugger to attach to code written in C++, the code needs to emit DebuggableAttribute. You can add this to your code automatically by linking with the /ASSEMBLYDEBUG linker option.

Visual Studio DebuggerDebugging Basics: Breakpoints

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

A breakpoint is a signal that tells the debugger to temporarily suspend execution of your program at a certain point. When execution is suspended at a breakpoint, your program is said to be in break mode. Entering break mode does not terminate or end the execution of your program. Execution can be resumed at any time.

You can think of break mode as being like a timeout. All the elements remain, functions, variables, and objects remain in memory, for example, but their movements and activities are suspended. During break mode, you can examine their positions and states to look for violations or bugs. You can make adjustments to the program while in break mode. You can change the value of a variable, for example. You can move the execution point, which changes the statement that will be executed next when execution resumes. In C++, C#, and Visual Basic, you can even make changes to the code itself while in break mode using a powerful feature called Edit and Continue.

Breakpoints provide a powerful tool that enables you to suspend execution where and when you need to. Rather than stepping through your code line-by-line or instruction-by-instruction, you can allow your program to run until it hits a breakpoint, then start to debug. This speeds up the debugging process enormously. Without this ability, it would be virtually impossible to debug a large program.

Many programming languages have statements or constructs that suspend execution and put your program into break mode. Visual Basic, for example, has the Stop statement. Breakpoints differ from these statements because breakpoints are not actual source code that has to be added to your program. You do not type a breakpoint statement into a source window. You request a breakpoint through the debugger interface, and the debugger sets it for you. To insert a line

Page 46: Error Handling in ASP

breakpoint, click in the gray margin next to the line where you want to set the breakpoint. More complex breakpoints can be handled through a full-featured Breakpoints window.

Breakpoints have many advantages over debugging constructs such as the Visual Basic Stop statement. Breakpoints can be deleted or changed without having to change your program's source code. Because breakpoints are not statements, they never produce any extra code when you build a release version of your program. If you use Stop statements in your program, you need to manually remove the Stop statements before building the release version, or use conditionals, as shown here:

#If DEBUG Then Stop#End If

If you want to disable a Stop statement temporarily, you need to locate the statement in your source code and comment it out:

' Stop

This is no problem if you only have one Stop statement. If you are debugging a large program with lots of Stop statements, however, searching for all of the statements and commenting each one out can be time consuming. With breakpoints, you can select and disable or enable any or all of your breakpoints from the Breakpoints window.

Finally, breakpoints have a big advantage over Stop statements in their flexibility. A Stop statement causes execution to break on the source line where the statement is located. You can set a breakpoint on a source line that does the same thing. Alternatively, you can also set a breakpoint on a function or a memory address, which cannot be done with Stop statements. In addition to these location breakpoints, the Visual Studio debugger offers data breakpoints for native only. A data breakpoint is set on a global or local variable, rather than a location in the code. Setting a data breakpoint causes execution to break when the value of that variable changes.

To provide even greater flexibility, the Visual Studio debugger enables you to set properties that modify the behavior of a breakpoint:

Hit Count enables you to determine how many times the breakpoint is hit before the debugger breaks execution. By default, the debugger breaks execution every time the breakpoint is hit. You can set a hit count to tell the debugger to break every two times the breakpoint is hit, or every 10 times, or every 512 times, any number you choose. Hit counts can be useful because some bugs do not appear the first time your program executes a loop, calls a function, or accesses a variable. Sometimes, the bug might not show up until the 100th or 1000th iteration. To debug such a problem, you can set a breakpoint with a hit count of 100 or 1000.

Condition is an expression that determines whether the breakpoint is hit or skipped. When the debugger reaches the breakpoint, it will evaluate the condition. The breakpoint will be hit only if the condition is satisfied. You can use a condition with a location

Page 47: Error Handling in ASP

breakpoint to stop at a specified location only when a certain condition is true. Suppose you are debugging a banking program, for example, where the account balance is never allowed to go below zero. You might set breakpoints at certain locations in the code and attach condition like balance < 0 to each one. When you run the program, execution will break at those locations only when the balance is less than zero. You can examine variables and program state at the first breakpoint location, then continue execution to the second breakpoint location, and so on.

Action specifies something that should occur when the breakpoint is hit. By default, the debugger breaks execution, but you can choose to print a message or run a Visual Studio macro instead. If you choose to print a message instead of breaking, the breakpoint has an effect very similar to a Trace statement. This method of using breakpoints is called tracepoints.

Filter provides a way to specify a process or thread for the breakpoint.

Note:One particularly useful technique is setting breakpoints in the Call Stack window. Using the Call Stack window, you can set a breakpoint on a particular function call. This can be especially useful when you are debugging a recursive function, a function that calls itself. If you break execution after a certain number of calls, you can use the Call Stack window to set a breakpoint on a previous call that has not yet returned. The debugger will encounter that breakpoint and break execution on the way out of the current calls.

Visual Studio DebuggerExecution Control

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

The Visual Studio debugger provides powerful commands for controlling the execution of your application. The following topics describe the tasks you can perform, using debugger commands, to control execution:

Starting (or Continuing) Execution

Page 48: Error Handling in ASP

Breaking Execution

Stopping Execution

Stepping Through Your Application

Running to a Specified Location

Setting the Execution Point

Visual Studio DebuggerViewing Data in the Debugger

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

The Visual Studio debugger provides a variety of tools for inspecting and modifying the state of your program. Most of these tools function only in break mode.

 DataTips

DataTips are one of the most convenient tools for viewing information about the variables and objects in your program during debugging. When the debugger is in break mode, you can view the value of a variable within the current scope by placing the mouse pointer over the variable in a source window. In Visual Studio 2005, DataTips have been enhanced to enable more convenient and powerful viewing of complex data types. For more information, see How to: Use DataTips.

 Visualizers

Visualizers are a new component of the Visual Studio debugger that enable you to view the contents of an object or variable in a meaningful way. For example, you can use the HTML visualizer to view an HTML string as it would be interpreted and displayed in a browser. You can access visualizers from DataTips, the Watch window, the Autos window, the Locals window, or the QuickWatch dialog box. For more information, see Visualizers.

 Variable Windows

Page 49: Error Handling in ASP

You can use Variable Windows to study variables, register contents, and expressions.

You can set the numeric format used in the debugger windows to decimal or hexadecimal. For more information, see Changing the Numeric Format of Debugger Windows.

 Other Debugger Windows

The following debugger windows offer important information about your program.

To view Try

Register contentsHow to: Use the Registers Window

Memory contents How to: Use the Memory Window Names of functions on the call stack

Parameter types

Parameter values

How to: Use the Call Stack Window

Assembly code generated by the compiler for your programHow to: Use the Disassembly Window

Threads — sequential streams of execution — created by your program

How to: Use the Threads Window

Modules (DLLs and EXEs) used by your program How to: Use the Modules WindowNote:

Your ability to inspect the program may be limited by whether the program was built with debug information, whether the debugger has access to the source code, and whether the common language runtime Just-In-Time (JIT) compiler is tracking debug information. If the Visual Studio debugger does not find debug information for your program, it reports "no matching symbolic information found". Debug information is generated by default when you build the debug configuration of your program. In the debugger cannot find symbols, you may need to specify a symbol path. For more information, see How to: Specify a Symbol Path. To aid in debugging system calls, you can install system debug symbols. For more information, see Installing System Debug Symbols.

Visual Studio DebuggerWhat's New in the Visual Studio Debugger

The debugger has been enhanced by the addition of the following features:

The Step Into Specific command now works with managed as well as native code. For more information, see How to: Step Into a Specific Function.

The debugger no longer steps into managed properties and operators by default. For more information, see How to: Step Into Properties and Operators in Managed Code.

Page 50: Error Handling in ASP

You can now step into .NET Framework source code when debugging. For more information, see How to: Debug .NET Framework Source.

 Changes in the Visual Studio 2008 Debugger

The Visual Studio 2008 debugger has been enhanced by the addition of the following features:

Remote debugging support for Windows Vista.

You can remote debug to or from a platform running the Windows Vista operating system. For more information, see How to: Set Up Remote Debugging.

Better support for debugging multithreaded applications.

Improvements to the Threads window, flagging threads of special interest, thread markers in a source window, and switching threads in a source window. For more information, see Debugging Multithreaded Applications.

Debugging support for LINQ programming.

You can debug LINQ queries, including LINQ to SQL Queries. For more information, see Debugging LINQ.

Debugging support for Windows Communications Foundation.

For more information, see Debugging WCF Services.

Better support for script debugging, including:o Client-side script files generated from server-side script now appear in Solution

Explorer. The Script Explorer window is no longer needed and has been removed. For more information, see How to: View Script Documents.

o Breakpoints set in server-side script files are automatically mapped to corresponding breakpoints in client-side script files. For more information, see How to: Set Breakpoints in Script.

o Easy attach to script processes. For more information, see How to: Attach to Script.

Improvements to the Debugger Automation model.

Improvements to Tracepoints, Modules Window, Exception Settings, and symbol path manipulation.

Better function evaluation.

Page 51: Error Handling in ASP

Improvements to function evaluation detection. Function evaluation now aborts if the debugger detects evaluation is waiting for a frozen thread.

Visual Studio DebuggerHow to: Set Up Remote Debugging

This topic applies to:

Edition Visual Basic C# C++ Web DeveloperExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default

To enable remote debugging, you can do one of two things:

Install the Remote Debugging Monitor (msvsmon.exe) on the remote computer and start it when you begin debugging.

Run the Remote Debugging Monitor remotely from a share.

Running the Remote Debugging Monitor from a file share is the easiest way to enable remote debugging. Visual Studio installs msvsmon.exe into these directories:

Install path\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\x86

Install path\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\x64

Install path\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\ia64

The IA64 components are available only with Visual Studio Team System.

When you install Visual Studio on a 64-bit operating system, remote debugging components for both 64-bit and x86 are installed.

When you install Visual Studio on an x86 operating system, remote debugging components for x86 are installed by default.  64-bit debugging components are installed if you choose the appropriate option during installation.

When you install the Remote Debugging Monitor on an x86 operating system, only the x86 remote debugging components are installed; there is no option for installing 64-bit components.

Page 52: Error Handling in ASP

By sharing out the Remote Debugger directory on the Visual Studio computer, you can run msvsmon.exe on the remote computer.

The following debugger features do not work when the Remote Debugging Monitor is run from a share:

Stepping into an XML Web service (manual attach is still possible). Automatically debugging a ASP.NET Web application (again, manual attach is still

possible).

As an alternative to running from a share, you can use the Visual Studio 2005 Remote Debugger CD to install the necessary remote debugging components on the remote computer. This installation provides access to all remote debugging features.

When you run the Remote Debugger installation on an x86 operating system, only the x86 remote debugging components are installed; there is no option for installing 64-bit components. If you run it on a 64-bit operating system, both x86 and 64-bit components are installed.

For certain debugging scenarios, you must install additional components.

To install remote debugging components

1. The Remote Debugger is available on the last disc of your Visual Studio installation set. Insert this disc in the remote computer.

For example, if you have four discs in your installation set, insert disc 4 in the remote computer. If you have a DVD instead of a CD, insert the DVD.

2. In Windows Explorer, open the CD/DVD. Locate the Remote Debugger folder (on the CD) or vs/Remote Debugger (on the DVD).

3. In the Remote Debugger folder, open the subfolder that matches your operating system (x86, x64, or IA64).

4. Start the copy of rdbgsetup.exe located in that subfolder, and follow the instructions to complete setup.

If you prefer, you can install the remote debugging components by copying the files manually. See Remote Debugging Components for a list of required components and their install locations.

Visual Studio includes separate versions of the Remote Debugging Monitor for 32-bit and 64-bit operating systems. If you use rdbgsetup.exe, the Remote Components Setup will automatically install the correct version of the Remote Debugging Monitor. If you decide to copy the files manually, you must make sure that you have copied the correct version.

Page 53: Error Handling in ASP

5. After you have installed the remote debugging components, you must make sure that you have the required permissions to debug a program on the remote computer. See Remote Debugging Permissions for a list of required permissions.

 Configuring the Windows Firewall

The Windows Firewall must be configured to enable remote debugging. When you start remote debugging for the first time, Visual Studio performs the necessary configuration on the Visual Studio host computer. Similarly, when you run the Remote Debugging Monitor on a remote computer for the first time, the Remote Debugging Monitor configures the Windows Firewall on that end.

In Windows XP, this configuration is transparent and automatic; however, in Windows Vista, the new security model requires that you grant permission before the software can configure the firewall. This permission is granted through the User Access Control dialog box. For a description of the new security model and User Access Control (UAC), see The Windows Vista Security Model.

When the Remote Debugging Monitor has to configure the Windows Firewall on the remote computer, the User Access Control dialog box appears on the remote computer. If the remote computer is not visible, you may not realize that the User Access Control dialog box has appeared on its monitor. In that case, you may mistakenly believe that remote debugging has stopped responding. In reality, the Remote Debugging Monitor is just waiting for someone to grant UAC permission on the remote computer.

One way to avoid this problem is to preconfigure the firewall on the remote computer by using the Remote Debugger Configuration Wizard.

It is highly unlikely that you will ever have to configure the Windows Firewall manually. If you do have to configure it manually, first see How to: Manually Configure the Windows XP Firewall for Remote Debugging or How to: Manually Configure the Windows Vista Firewall for Remote Debugging.

To configure the Windows Firewall by using the Remote Debugger Configuration Wizard

1. Make sure that the remote debugging components have been installed on the computer.2. Click Start, point to All Programs, point to Visual Studio 9.0, and then click Visual

Studio Remote Debugger Configuration Wizard.

3. Click Start, point to All Programs, point to Visual Studio 9.0, and then click Remote Debugger.

4. Follow the instructions in the Remote Debugger Configuration Wizard.

 Enabling Web Server Debugging

Page 54: Error Handling in ASP

To enable Web server debugging on Windows Vista or Windows XP SP2

To enable Web server debugging on Windows Vista or Windows XP SP2, you have to perform some additional steps:

o For Windows Vista, see How to: Enable Web Server Debugging on Windows Vista.

o For Windows XP SP2, see How to: Enable Web Server Debugging on Windows XP SP2.

 Starting Remote Debugging

To start remote debugging

1. Make sure that you have the necessary remote debugging permissions on the remote computer. For more information, see Remote Debugging Permissions.

2. For remote debugging other than SQL, make sure that you are running the Remote Debugging Monitor on the remote computer. For more information, see How to: Run the Remote Debugging Monitor.

When you are debugging SQL, the Remote Debugging Monitor will start automatically during debugging.

3. Start Visual Studio on the debugger host.4. Use Visual Studio to attach to a program that you want to debug on the remote computer,

or start a program that you want to debug on the remote computer. For more information, see How to: Attach to a Running Process.

Visual Web DeveloperWalkthrough: Debugging Web Pages in Visual Web Developer

Visual Web Developer provides you with tools to help track down errors in your ASP.NET Web pages. In this walkthrough, you will work with the debugger, which allows you to step through the page's code line by line and examine the values of variables.

In the walkthrough, you will create a Web page that contains a simple calculator that squares a number. After creating the page (which will include a deliberate error), you will use the debugger to examine the page as it is running.

Tasks illustrated in this walkthrough include:

Setting breakpoints. Invoking debugger from a Web Forms page in a file system Web site.

Page 55: Error Handling in ASP

 Prerequisites

In order to complete this walkthrough, you will need:

Visual Web Developer and the .NET Framework.

You should also have a general understanding of working in Visual Web Developer. For an introduction to Visual Web Developer, see Walkthrough: Creating a Basic Web Page in Visual Web Developer.

 Creating the Web Site and Page

In the first part of the walkthrough, you will create a page that you can debug.

If you have already created a Web site in Visual Web Developer (for example, by working with the topic Walkthrough: Creating a Basic Web Page in Visual Web Developer ), you can use that Web site and skip to "Adding Controls to Debug" later in this walkthrough. Otherwise, create a new Web site and page by following these steps.

To create a file system Web site

1. Open Visual Web Developer. 2. On the File menu, click New Web Site.

The New Web Site dialog box appears.

3. Under Visual Studio installed templates, click ASP.NET Web Site. 4. In the Location box, click File System and then type the name of the folder where you

want to keep the pages of your Web site.

For example, type the folder name C:\WebSites.

5. In the Language list, click the programming language that you prefer to work in.

The programming language you choose will be the default for your Web site. However, you can use multiple languages in the same Web application by creating pages and components in different programming languages. For information on creating components using different languages, see Shared Code Folders in ASP.NET Web Sites.

6. Click OK.

Visual Web Developer creates the folder and a new page named Default.aspx.

Creating a Page to Debug

Page 56: Error Handling in ASP

You will begin by creating a new page. For this walkthrough, it is important that you create a new page as specified in the following procedure.

To add a page to the Web site

1. Close the Default.aspx page. 2. In Solution Explorer, right-click the name of your Web site (for example, C:\WebSite)

and choose Add New Item.

3. Under Visual Studio installed templates, choose Web Form.

4. In the Name box, type DebugPage.aspx.

5. From the Language list, choose the programming language you prefer to use.

6. Be sure that the Place code in separate file check box is cleared.

In this walkthrough, you are creating a single-file page with the code and HTML in the same page. The code for ASP.NET pages can be located either in the page or in a separate class file. To learn more about keeping the code in a separate file, see Walkthrough: Creating a Basic Web Page with Code Separation in Visual Web Developer .

7. Click Add.

Visual Web Developer creates the new page and opens it in Source view.

You can now add some controls to the page and then add code. The code will be simple, but enough to allow you to add breakpoints later.

To add controls and code for debugging

1. Switch to Design view, and then from the Standard folder of the Toolbox, drag the following controls onto the page and set their properties as indicated:

Control Properties

Label ID: CaptionLabel

Text: (empty)

TextBox ID: NumberTextBox

Text: (empty)

Button ID: SquareButton

Text: Square Label ID: ResultLabel

Page 57: Error Handling in ASP

Text: (empty) Note:

For this walkthrough, the layout of the page is not important. 2. Double-click the Button control to create a Click handler for it. 3. Add logic to the Click handler to call a function called Square to square the number entered by

the user. The handler might look like the following example.

Note:The code example deliberately does not include error checking.

4. Visual Basic

5. Sub SquareButton_Click(ByVal sender As Object, _6. ByVal e As System.EventArgs)7. Dim number As Integer8. Dim result As Integer9. number = CInt(NumberTextBox.Text)10. result = Square(number)11. ResultLabel.Text = CStr(number) & " squared is " & CStr(result)12. End Sub

13. C#

14. protected void SquareButton_Click(object sender, System.EventArgs e)15. {16. int number, result; 17. number = System.Convert.ToInt32(NumberTextBox.Text);18. result = Square(number);19. ResultLabel.Text = NumberTextBox.Text + 20. " squared is " + result.ToString();21. }

22. Create the function that squares the number. Include a bug in the code to add the number to itself instead of multiplying it. The code might look like the following example.

Visual Basic

Function Square(number As Integer) As Integer Square = number + numberEnd Function

C#

int Square(int number ){ int Square; Square = number + number; return Square;}

You can also add code to the page that will change the text of the label depending on whether this is the first time the page is running.

To change the caption Label control

Page 58: Error Handling in ASP

1. In Design view, double-click the design surface (not a control) to create a Page_Load event handler.

2. Set the text of the Caption Label control to Enter a number: if this is the first time the page is running, or Enter another number: otherwise. The handler will look like the following code example.

Visual Basic

Sub Page_Load(ByVal sender As Object, ByVal e as System.EventArgs) If Page.IsPostBack = False Then CaptionLabel.Text = "Enter a number: " Else CaptionLabel.Text = "Enter another number: " End IfEnd Sub

C#

if(Page.IsPostBack == false){ CaptionLabel.Text = "Enter a number: ";}else { CaptionLabel.Text = "Enter another number: " ;}

Testing the Page

To make sure the page is working, run it in its current state.

To run the page

1. Save the page. 2. Press CTRL+F5 to run the page.

3. Enter the number 3 and press the Square button.

Note that the result is incorrect, because there is a bug in the program. The correct result is 9.

4. Close the browser.

 Debugging the Page

In this part of the walkthrough, you will use the debugger to examine the page code line by line as it is running, add breakpoints to the code, and then run the page in Debug mode.

You will start by setting breakpoints in your code. A breakpoint is a line in your code where execution stops and the debugger is invoked.

Page 59: Error Handling in ASP

To set breakpoints

1. Switch to Source view. 2. Right-click the following line, choose Breakpoint, and then choose Insert Breakpoint.

Note:You can toggle breakpoints by pressing F9.

3. Visual Basic

4. If Page.IsPostBack = False Then

5. C#

6. if(Page.IsPostBack == false)

7. Set another breakpoint on the following line of the SquareButton_Click handler:

Visual Basic

result = Square(number)

C#

result = Square(number);Note:

You cannot set a breakpoint on a statement that declares a variable.

With at least one breakpoint set, you are ready to run the debugger.

To run the debugger

1. From the Debug menu, choose Start Debugging (or press F5) to run the page in debug mode.

If you have never run the debugger before, your application probably is not configured to support debugging. By default, debugging is turned off in applications both for performance (pages run more slowly in the debugger) and for security reasons. Visual Web Developer displays a message telling you what it must do to enabled debugging.

The switch to enable debugging is stored as a setting in the Web.config file, which maintains various site-specific configuration options. If the Web.config file does not exist, Visual Web Developer will both create the file and make the appropriate debugger setting.

If the Web.config file already exists but debugging is not enabled, you will see a slightly different message telling you that Visual Web Developer will modify the Web.config file.

2. If you see the message telling you that debugging has not been enabled, click OK to enable debugging.

Page 60: Error Handling in ASP

In Visual Web Developer, the designer changes to debug mode displaying the code for your page and some debugger windows.

The debugger runs your page line by line. When the debugger gets to the line with the breakpoint, it stops and highlights the line.

Because the breakpoint is in the Page_Load handler, the page has not finished processing yet. The browser is open, but the page is not yet displayed.

3. In the Debug menu, click Windows, click Watch, and then click Watch 1. Note:

If you are using Visual Web Developer Express Edition, the debugger offers only a single Watch window.

4. This opens a Watch window, where you can specify the values you want to track.

5. In the editor, right-click the IsPostBack portion of the Page.IsPostBack expression, and then click Add Watch.

This adds the expression to the Watch window and displays the current value of the property (false) is displayed in the Value column. If you prefer, you can type the name of a variable or property in the Name column of the Watch window.

6. From the Debug menu, choose Continue to continue execution, or press F5.

The Continue command tells the debugger to proceed until it gets to the next breakpoint. The Page_Load event handler finishes processing and the page is displayed in the browser.

7. Enter the value 2 into the text box and click the Square button.

The debugger is displayed again, with the breakpoint on the line in the Page_Load handler. This time, the Watch window shows you that the value of Page.IsPostBack is true.

8. Press F5 again to continue.

The debugger processes the Page_Load handler and enters the SquareButton_Click handler, where it stops on the second breakpoint you set.

9. In the Debug menu, click Windows and then click Locals.

This opens the Locals window, which displays the values of all variables and objects that are in scope at the current line being executed. The Locals window provides an alternative way for you to view these values, with the advantage that you do not have to explicitly set a watch on the elements, but with the disadvantage that the window might contain more information than you want to see at once.

Page 61: Error Handling in ASP

In the Locals window, you see that the value of number is 2 and the value of result is 0.

Note:You can also see the value of any variable in the program by holding the mouse pointer over it.

10. In the Value column of the Locals window, right-click the line for the number variable and select Edit value. Edit the value of the number variable and change it to 5.

The value 2 for the variable number is not a good test of the program, because adding and squaring 2 both result in 4. Therefore, while the program is running, you can change the value of this variable.

11. From the Debug menu, choose Step Into to step into the Square function, or press F11.

The Step Into command causes the debugger to execute a line and then stop again.

12. Continue stepping by pressing F11 until you reach the following line of code.

Visual Basic

ResultLabel.Text = CStr(number) & " squared is " & CStr(result)

C#

ResultLabel.Text = NumberTextBox.Text + " squared is " + result.ToString();

The debugger walks through your code line by line. When the debugger executes the Square function, you can use the Locals window to check the data passed to the function (number) and the return value of the function (Square).

13. In the Debug menu, click Windows and then Immediate.

The Immediate window allows you to execute commands. You can use the window to evaluate expressions (for example, to get the value of a property).

14. In the Immediate window, type the following expression and press Enter. 15. ? NumberTextBox.Text

The question mark (?) is an operator in the Immediate window that evaluates the expression following it. In this example, you are evaluating the Text property of the NumberTextBox control on the page. You can evaluate any variable, object property, or expression that combine these, using the same syntax that you would use in code.

16. In the Immediate window, type the following and press Enter: 17. NumberTextBox.Text = "5"

Page 62: Error Handling in ASP

In addition to evaluating expressions, the Immediate window allows you to change variables or properties

18. Press F5 to continue running the program.

When the page appears, it displays the result of passing 5 to the Square function. In addition, the text in the text box has been changed to 5.

The result you see — 10 — is not correct, since 10 is not the square of 5. You can now fix the bug.

To fix the bug and test again

1. Switch from the browser to Visual Web Developer. Note:

Do not close the browser window. 2. In the Square function, change the "+" operator to the "*" operator.

Because the code is not currently running (the page has finished processing), you are in edit mode and can make permanent changes.

3. Press CTRL+S to save the page. 4. From the Debug menu, choose Delete All Breakpoints so that the page will not stop each time

you run it.

Note:You can also clear breakpoints by pressing CTRL+SHIFT+F9.

5. Switch to the browser window.

6. Enter 5 in the text box and click the button.

This time, when you run the page and enter a value, it is squared correctly. The temporary changes you made earlier, such as changing the Text property of the NumberTextBox control, have not been persisted, because they applied only when the page was running the last time.

7. Close the browser to stop the debugger.

 Next Steps

The debugger includes additional features to help you work with your code. In addition, you might want to learn about techniques for handling error conditions and ways in which you can monitor page processing at run time. For example, you might want to explore tracing. For details, see Walkthrough: Using Tracing in Visual Web Developer to Help Find Web Page Errors.

Page 63: Error Handling in ASP

Visual Studio DebuggerDebugging ASP.NET and AJAX Applications

Debugging ASP.NET Web applications is similar to debugging a Windows Form or any other Windows application because both kinds of applications involve controls and events. However, there are also basic differences between the two kinds of applications:

Keeping track of state is more complex in a Web application. In a Windows application, the code to be debugged is mostly in one location; in a Web

application, the code can be on the client and on the server. While ASP.NET code is all on the server, there might also be JavaScript or Visual Basic code on the client.

 In This Section Preparing to Debug ASP.NET

Describes the steps that are required to enable debugging of ASP.NET applications.

Debugging Web Applications and Services

Discusses how to debug a ASP.NET application, including AJAX-enabled script applications, and XML Web services.

Visual Studio DebuggerPreparing to Debug ASP.NET

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

This section describes how to set up Visual Studio to debug an ASP.NET or WCF application.

 In This Section ASP.NET Debugging: System Requirements

Describes the operating system requirements for debugging ASP.NET or WCF Web applications by using Visual Studio.

Page 64: Error Handling in ASP

Limitations on WCF Debugging

Explains limits about how to debug WCF Web applications by using Visual Studio.

How to: Enable Debugging for ASP.NET Applications

Discusses setting debug mode for an ASP.NET application. Information includes a description of Web.config files, suggestions for editing the file, sample code, and the behavior of hierarchical configuration files.

How to: Debug Web Applications on a Remote Server

Lists prerequisites for debugging a Web application on a remote server.

How to: Configure IIS on Windows Server 2003

Discusses special configuration steps needed for debugging system requirements for debugging ASP.NET on Windows Server 2003.

How to: Debug a Self-Hosted WCF Service

Describes steps for debugging a WCF service that is not hosted on IIS or the ASP.NET Development Server.

Visual Studio DebuggerHow to: Configure IIS on Windows Server 2003

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

When you are debugging an application on Windows Server 2003, the user account that creates the application pool must be in the IIS_WPG group. Otherwise, you will not be able to debug the application, even if the user is an Administrator on the computer.

To configure IIS on Windows Server 2003

Page 65: Error Handling in ASP

1. Click Start and point to All Programs. 2. Click Administrative Tools, and then click Internet Information Services.

3. Right-click your computer name in the left pane, and then click Security.

4. On the first screen of the IIS Security Lockdown Wizard, click Next.

5. Verify that HTTP is set to Automatic, and click Next.

6. In the Request Handlers list, check ASP.NET, and each instance of <Microsoft.NET Framework install directory>\aspnet_isapi.dll.

7. Click Next.

8. Click Finish to complete the wizard.

Visual Studio DebuggerHow to: Run the Worker Process Under a User Account

This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

To set up your computer so that you can run the ASP.NET worker process (aspnet_wp.exe or w3wp.exe) under a user account, follow these steps.

 Procedure

To run aspnet_wp.exe under a user account

1. Open the machine.config file, located on your computer in the CONFIG folder under the path where you installed the runtime.

2. Find the <processModel> section and change the user and password attributes to the name and password of the user account you want aspnet_wp.exe to run under.

3. Save the machine.config file.

Page 66: Error Handling in ASP

4. On Windows Server 2003, IIS 6.0 is installed by default. The corresponding worker process is w3wp.exe.To run in IIS 5.0 mode with aspnet_wp.exe as the worker process, you must follow these steps:

1. Click Start, click Administrative Tools and then choose Internet Information Services.

2. In the Internet Information Services dialog box, right-click the Web Sites folder and choose Properties.

3. In the Web Sites Properties dialog box, choose Service.

4. Select Run WWW service in IIS5.0 isolation mode.

5. Close the Properties dialog box and Internet Services Manager.

5. Open a Windows Command Prompt and reset the server by running:

6. iisreset

— or —

net stop iisadmin /ynet start w3svc

7. Locate the Temporary ASP.NET Files folder, which should be in the same path as the CONFIG folder. Right-click the Temporary ASP.NET Files folder and choose Properties on the shortcut menu.

8. In the Temporary ASP.NET Files Properties dialog box, click the Security tab.

9. Click Advanced.

10. In the Advanced Security Settings for Temporary ASP.Net Files dialog box, click Add.

The the Select User, Computer, or Group dialog box appears.

11. Type the user name in the Enter the object name to select box, and then click OK. The user name must follow this format: DomainName\UserName.

12. In the Permission Entry for Temporary ASP.NET Files dialog box, give the user Full Control, and then click OK to close the Entry for Temporary ASP.NET Files dialog box.

13. A Security dialog box will appear, and asks if you really want to change the permissions on a system folder. Click Yes.

14. Click OK to close the Temporary ASP.NET Files Properties dialog box.

Visual Studio DebuggerHow to: Debug Web Applications on a Remote Server

This topic applies to:

Page 67: Error Handling in ASP

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

With the Visual Studio debugger, you can debug a Web application transparently on the local computer or a remote server. This means that the debugger functions the same way and allows you to use the same features on either computer. For remote debugging to work correctly, however, there are some prerequisites.

Visual Studio remote debugging components must be installed on the server you want to debug. For more information, see Setting Up Remote Debugging.

By default, the ASP.NET worker process runs as an ASPNET user process. As a result, you must have Administrator privileges on the computer where ASP.NET runs to debug it. The name of the ASP.NET worker process varies by debug scenario and version of IIS. For more information, see How to: Find the Name of the ASP.NET Process.

In Visual C++, the project must be set up to connect by using DCOM instead of TCP/IP. To set this property, follow these steps:

To enable Visual C++ projects to connect through DCOM

1. Open the <Project>Property Pages dialog box.2. Open the Configuration Properties node if not already opened.

3. Select the Debugging node under Configuration Properties.

4. Choose Remote Windows Debugger under Debugger to launch.

5. Choose Remote with Windows authentication under Connection.

For more information, see Project Settings for a C or C++ Debug Configuration.

Visual Studio DebuggerHow to: Enable Debugging for ASP.NET Applications

This topic applies to:

Edition Visual Basic C# C++ Web Developer Express

Page 68: Error Handling in ASP

StandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

To enable debugging, you must enable it in both the Project Properties page and in the application's web.config file.

Note:The dialog boxes and menu commands you see might differ from those described in Help depending on your active settings or edition. To change your settings, choose Import and Export Settings on the Tools menu. For more information, see Visual Studio Settings.

To enable ASP.NET debugging in the project properties (Visual Basic/C#)

1. In Solution Explorer, right-click the name of a Web project and select Property Pages.

The <Project> Property Pages appears.

2. Click the Web tab.3. Under Debuggers, select the ASP.NET check box.

To enable debugging in the web.config file

1. Open the web.config file by using any standard text editor or XML parser. 1. You cannot access the file remotely by using a Web browser, however. For

security reasons, ASP.NET configures Microsoft IIS to help prevent direct browser access to Web.config files. If you try to access a configuration file by using a browser, you will get HTTP access error 403 (forbidden).

2. Web.config is an XML file, and so contains nested sections marked by tags. The following example shows a typical Web.config file. Modify the file by following these steps:

1. Locate the <compilation> tag. This marks the beginning of the <compilation> section.

2. Inside the <compilation> tag, you will create the debug attribute. In the following example , debug is the second attribute that is specified in the <compilation> tag, but the order is not important.

Page 69: Error Handling in ASP

3. Attributes are case-sensitive, therefore make sure that you specify "debug", not "Debug" or "DEBUG."

4. Set debug to true, as shown in the following code example.

3. If you do not set the debug attribute to true and try to launch a debugging session, a dialog box will appear, offering to create a web.config file with the attribute set. Accept, and continue to debug.

 Example <configuration> <system.web> <compilation defaultLanguage="VB" debug="true" numRecompilesBeforeAppRestart="15"> <compilers> <compiler language="VB;VBScript" extension=".cls" type="Microsoft.VisualBasic.VBCodeProvider,system, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" /> < compiler language="C#;Csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,system, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </compilers>

<assemblies>"" <add assembly="ADODB" /> <add assembly="*" /> </assemblies>

<namespaces> <add namespace="System.Web" /> <add namespace="System.Web.UI" /> <add namespace="System.Web.UI.WebControls" /> <add namespace="System.Web.UI.HtmlControls" /> </namespaces>

</compilation> </system.web></configuration>

 Robust Programming

ASP.NET automatically detects any changes to Web.config files and applies the new configuration settings. You do not have to restart the computer or restart the IIS server for changes to take effect.

A Web site can contain multiple virtual directories and subdirectories, and Web.config files may exist in each one. ASP.NET applications inherit settings from Web.config files at higher levels in the URL path. Hierarchical configuration files allow you to change settings for several ASP.NET applications at the same time, such as for all applications below it in the hierarchy. However, if debug is set in a file lower in the hierarchy, it will override the higher value.

Page 70: Error Handling in ASP

For example, you could specify debug="true" in www.microsoft.com/aaa/Web.config, and any application in the aaa folder or in any subfolder of aaa will inherit that setting. So if your ASP.NET application is at www.microsoft.com/aaa/bbb, it will inherit that setting, as will any ASP.NET applications in www.microsoft.com/aaa/ccc, www.microsoft.com/aaa/ddd, and so on. The only exception is if one of those applications overrides the setting by means of its own lower Web.config file.

Enabling debug mode will greatly affect the performance of your ASP.NET application. Remember to disable debug mode before you deploy a release application or conduct performance measurements.

Visual Studio DebuggerDebugging Web Applications and Services

This section explains how to debug several types of Web applications and Web services.

 In This Section How to: Debug Web Applications and Web Services

Describes how to debug an ASP.NET project still under development.

Debugging Deployed Web Applications and Web Services

Explains how to debug an already-deployed ASP.NET Web application.

Client-Side Script Debugging

Discusses testing scripts and client-side scripts in ASP.NET pages.

Walkthrough: Debugging a Web Form

Illustrates how to debug an ASP.NET Web application.

How to: Debug ASP.NET Exceptions

Explains how to deal with exceptions that occur while you debug ASP.NET applications.

Debugging XML Web Services

Illustrates how to debug an XML Web service.

Visual Studio DebuggerHow to: Debug Web Applications and Web Services

This topic applies to:

Page 71: Error Handling in ASP

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

Table legend:

AppliesDoes not applyCommand or commands hidden by default.

ASP.NET is the primary technology for developing Web applications in Visual Studio. The Visual Studio debugger provides powerful tools for debugging ASP.NET Web applications locally or on a remote server. This topic describes how to debug an ASP.NET project during development. For information about how to debug a ASP.NET Web application already deployed on a production server, see Debugging Deployed Web Applications and Web Services.

To debug an ASP.NET application:

You must have required permissions. For more information, see ASP.NET Debugging: System Requirements.

ASP.NET debugging must be enabled in Project Properties.

The configuration file of your application (Web.config) must be set to debug mode. Debug mode causes ASP.NET to generate symbols for dynamically generated files and enables the debugger to attach to the ASP.NET application. Visual Studio sets this automatically when you start to debug, if you created your project from the Web projects template.

For more information, see How to: Enable Debugging for ASP.NET Applications.

To debug a Web application during development

1. On the Debug menu, click Start to begin debugging the Web application.

Visual Studio builds the Web application project, deploys the application if necessary, starts the ASP.NET Development Server if you are debugging locally, and attaches to the ASP.NET worker process.

2. Use the Debugger to set and clear breakpoints, step, and perform other debugging operations, as you would for any application.

For more information, see Debugger Roadmap.

3. On the Debug menu, click Stop Debugging to end the debugging session, or, on the File menu in Internet Explorer, click Close.

Page 72: Error Handling in ASP

4. Visual Studio Debugger5. Debugging Deployed Web Applications and Web Services6. This topic applies to:

Edition Visual Basic C# C++ Web Developer ExpressStandardPro and Team

7. Table legend:

AppliesDoes not applyCommand or commands hidden by default.8. If you need to debug a Web application that is running on a production server, this should

be done with caution. If you attach to the ASP.NET worker process for debugging and hit a breakpoint, for example, all managed code in the worker process halts. Halting all managed code in the worker process can cause a work stoppage for all users on the server. Before you debug on a production server, consider the potential impact on production work.

9. To use Visual Studio to debug a deployed application, you must attach to the ASP.NET worker process and make sure that the debugger has access to symbols for the application. You must also locate and open the source files for the application. For more information, see Managing Symbols and Source Code, How to: Find the Name of the ASP.NET Process, and ASP.NET Debugging: System Requirements.

Note:Many ASP.NET Web applications reference DLLs that contain business logic or other useful code. Such a reference automatically copies the DLL from your local computer to the \bin folder of the Web application's virtual directory. When you are debugging, remember that your Web application is referencing that copy of the DLL and not the copy on your local computer.

10. The process for attaching to the ASP.NET worker process is the same as attaching to any other remote process. When you are attached, if you do not have the correct project open, a dialog box appears when the application breaks. This dialog box asks for the location of the source files for the application. The file name that you specify in the dialog box must match the file name specified in the debug symbols on the Web server. For more information, see Attaching to Running Processes.

Visual StudioDebugging Client-Side Scripts

The Microsoft Visual Studio .NET debugger provides you with a comprehensive debugging environment for testing and correcting errors in your Web document scripts. You can use the Visual Studio .NET debugger to test scripts written in Microsoft Visual Basic Scripting Edition (VBScript) and Microsoft JScript.

Page 73: Error Handling in ASP

You can use the Visual Studio .NET debugger to debug client-side scripts in an ASP.NET page. Client-side scripts consist of statements that appear on the HTML page. Microsoft Internet Explorer executes the script when the document is loaded or in response to an event (such as a button click).

Setting a Breakpoint in Client-Side Script

If you want to set a breakpoint in client-side script, you cannot just set the breakpoint in the project .aspx file. The .aspx file is a server-side document, and breakpoints set there are not translated to the client-side document. Instead, you can set a client-side breakpoint using either of the following methods.

To set a breakpoint in client-side script

Write all the client-side script in a single function and set a function breakpoint on that function.

–or–

Open the client-side script from the Running Documents window and set the breakpoint there.

Enabling Script Debugging

Note   Script debugging is disabled in Internet Explorer by default. To debug a client-side script application, you must first enable script debugging in Internet Explorer.

To enable script debugging in Internet Explorer 5.5 or later

1. From the Tools menu, choose Internet Options.2. In the Internet Options dialog box, choose the Advanced tab.

3. In the Browsing category, clear the Disable script debugging check box.

4. Click OK.

In addition, to hit breakpoints in client-side script, a cookie called ASPCLIENTDEBUG cookie must be set. If this cookie is not set automatically, you can set it manually using the following procedure.

To manually set ASPCLIENTDEBUG cookie

1. Create an HTML text file that contains the following code: 2. <html>3. <head>4.5. <script language="JavaScript">

Page 74: Error Handling in ASP

6.7. function set ()8. {9. var expdate = new Date(); 10. expdate.setMonth(expdate.getMonth()+6);11. alert("setting cookie \""+form1.txtName.value+"\"

to \""+form1.txtValue.value+"\"");12. setCookie(form1.txtName.value, form1.txtValue.value, expdate); 13. }14.15. function get ()16. {17. alert("getting cookie \""+form1.txtName.value+"\"");18. var c = getCookie(form1.txtName.value);19. alert( "cookie = "+c );20.21. form1.txtValue.value = c;22. }23.24. function getCookie (sCookieName)25. {26. var sName=sCookieName+"=", ichSt, ichEnd;27. var sCookie=document.cookie;28.29. if ( sCookie.length && ( -1 != (ichSt =

sCookie.indexOf(sName)) ) )30. {31. if (-1 == ( ichEnd = sCookie.indexOf(";",ichSt+sName.length) )

)32. ichEnd = sCookie.length;33. return unescape(sCookie.substring(ichSt+sName.length,ichEnd));34. }35. 36. return null;

} function setCookie (sName, vValue){ var argv = setCookie.arguments, argc = setCookie.arguments.length; var sExpDate = (argc > 2) ? "; expires="+argv[2].toGMTString() : ""; var sPath = (argc > 3) ? "; path="+argv[3] : ""; var sDomain = (argc > 4) ? "; domain="+argv[4] : ""; var sSecure = (argc > 5) && argv[5] ? "; secure" : ""; document.cookie = sName + "=" + escape(vValue,0) + sExpDate + sPath + sDomain + sSecure + ";";} function deleteCookie (sName){ document.cookie = sName + "=" + getCookie(sName) + "; expires=" + (new Date()).toGMTString() + ";";}

</script>

</head>

Page 75: Error Handling in ASP

<body>

<form name=form1> cookie name:<input type="text" name="txtName" value="ASPCLIENTDEBUG"><p> cookie value:<input type="text" name="txtValue" value="doesn't matter"><p> <input type="button" value="Set Cookie" onClick="set()"> <input type="button" value="Get Cookie" onClick="get()"></form></body></html>

1. Save the file as cookie.html.2. Copy the file to

c:\inetput\wwwroot

3. In the Internet Explorer Address box, type:

http://localhost/cookie.html

4. In the http://localhost/cookie.html window, click the Set Cookie button.

Better Error Messages For Script Debugging

Visual Studio .NET 2003 provides enhanced error messages for common script debugging problems. You will normally not see these messages unless you attach to Internet Explorer manually instead of having the debugger launch Internet Explorer automatically. If you encounter a problem, use the following procedure to manually attach and get more information.

To manually attach

1. From the Debug menu, choose Processes.

The Processes dialog box appears.

2. If you have already started debugging, go to the list of Debugged Processes. Select the process you are debugging and click Detach.

3. In the Available Processes box, find Internet Explorer (iexplore.exe), select it, and click Attach.

4. In the Attach to Process dialog box, under Choose the program types that you want to debug, select only Script.

5. Click OK.

6. At this point, an error message box may appear. If it does, click the Help button to get more information.

Visual Studio

Debugging Client-Side Scripts in a Web Page

Page 76: Error Handling in ASP

Using the Visual Studio .NET debugger, you can perform the following tasks when debugging client-side script in a Web page:

View the source code of the Web page (.htm, .html, .asp, .aspx) that you are debugging. Control the pace of script execution with breakpoints and stepping.

View and change variable and property values with several debugging windows including the Command window and Watch window.

View and control script flow with the Call Stack window.

Note To debug script you must enable script debugging in Internet Explorer.

Viewing Source

When you work with the Microsoft Visual Studio .NET debugger, you see the script that you are debugging in a read-only editor in the IDE. You cannot change the text in the window — documents are read-only while you are debugging. However, you can save the document under a new name, then open the document and modify it.

Controlling Program Execution

To control program execution, you set breakpoints, which are places where the script should pause and call the debugger. When you set breakpoints, the line containing the breakpoint is highlighted in the editor.

After setting a breakpoint, you run the document containing the script. When execution reaches the first breakpoint, the script pauses and starts the debugger. The current line is marked in the editor with a yellow box.

After reaching a breakpoint, you can execute, or step into, individual lines in your script. As you step through lines, the script executes and you can see the effect of each line.

If you reach a point in your script that calls another procedure (a function, subroutine) you enter (step into) the procedure or run (step over) it and stop at the next line. At any point, you can jump to the end (step out) of the current procedure and proceed to the next breakpoint.

Viewing and Changing Values

While debugging, you can view and change the values of variables or properties. Because you are making changes directly to a running script, you can affect the way that the script executes by changing values in it. After changing values, you can continue with the script and see the effect of your change.

Page 77: Error Handling in ASP

To view and change values, you use the Immediate window. You can evaluate any expression in the window and can enter script commands and see their effect. You can enter commands in the language of the script currently executing.

Viewing and Controlling Program Flow

The Call Stack window allows you to trace the procedures and functions that are currently executing. While debugging, you can view the flow of control from procedure to procedure. You can also select a procedure in the call stack and jump directly to it and then continue running the script.

Visual Studio

Debugging Client-Side Scripts in Your Application

There are several ways that you can debug the client-side script in your application:

From Microsoft Internet Explorer Using the Running Documents window

In a Script

In Response to an Error

Note To debug script you must enable script debugging in Internet Explorer.

From Microsoft Internet Explorer

To debug a client-side script from Microsoft Internet Explorer

1. From the View menu, select Script Debugger and click Open. This launches the Just-In-Time Debugging dialog box.

2. From Possible Debuggers list in the Just-In-Time Debugging dialog box, select New Instance of Microsoft Development Environment and click Yes.

3. In the Attach to Process dialog box, in the Choose the program types that you want to debug box, select the Script check box and click OK.

To specify that the debugger stop at the first statement of scripts

1. From the View menu, select Script Debugger and click Break at Next Statement. This launches the Just-In-Time Debugging dialog box.

2. From Possible Debuggers list in the Just-In-Time Debugging dialog box, select New Instance of Microsoft Development Environment and click Yes.

3. In the Attach to Process dialog box, in the Choose the program types that you want to debug box, select the Script check box and click OK.

Page 78: Error Handling in ASP

From now on, when any script is executed, the debugger stops at the first statement of the script.

Using the Running Documents Window

The Running Documents window shows a list of documents that are currently loaded into the program you are debugging. For example, in an HTML frameset, the Running Documents window can show you the pages currently loaded in the browser. You can use the Running Documents window to open a document and set a breakpoint inside the script code. You can also use this window to see and debug code that is generated by script on the server and sent to the client.

In a Script

When writing a script, include a Stop statement (VBScript) or debugger statement (JScript). When script execution reaches that line, the Visual Studio .NET debugger is launched.

In Response to an Error

If the browser or server encounters a syntax error or run time error in a script, it displays a message that offers you the opportunity to start the debugger at the line where the error occurred.

Visual Studio

Debugging ASP.NET Web Services

Debugging an XML Web service created with ASP.NET is similar to debugging an ASP.NET Web application. For more information, see Debugging ASP.NET Web Applications. You can perform many of the same operations, such as setting breakpoints, stepping through code, and viewing the state of your program using various debugger windows.

When a managed client calls a managed XML Web service, the Visual Studio .NET debugger can automatically step between the client and the XML Web service. For details, see Stepping Into an XML Web Service.

The following sections explain some useful techniques for debugging XML Web services:

Debugging an XML Web Service on //localhost Debugging an XML Web Service on a Remote Server

Error While Trying To Run Project

Debugging a Deployed XML Web Service

Page 79: Error Handling in ASP

Debugging an XML Web Service on http://localhost

During development, you may want to debug an XML Web service on http://localhost rather than a remote server. For more information, see Debugging a Deployed XML Web Service.

To debug an XML Web service during development

1. If you have not already done so, set the debug mode attribute in the application's Web.config configuration file. For more information, see Debug Mode in ASP.NET Applications. Debug mode tells ASP.NET to generate symbols for dynamically generated files and enables the debugger to attach to the ASP.NET application. (Projects created from the XML Web service template should have this set automatically.)

2. In Visual Studio .NET, use the <Project> Property Pages to set the project properties for XML Web service debugging.

3. To start debugging the XML Web service, choose Start from the Debug menu.

Visual Studio .NET builds the XML Web service project and deploys the application and its symbol information.

4. Use the debugger to set and clear breakpoints, step, and perform other debugging operations, as you would for any application. For more information, see Using the Debugger.

5. To end the debugging session in Visual Studio .NET, choose the Stop Debugging command on the Debug menu or, in Internet Explorer, choose Close from the File menu.

Debugging an XML Web Service on a Remote Server

With the Visual Studio .NET debugger, you can debug an XML Web service transparently on the local machine or a remote server. This means that the debugger functions the same way and allows you to use the same features on either machine. For remote debugging to work properly, however, there are some prerequisites.

Visual Studio .NET remote debugging components must be installed on the server you want to debug. (For more information, see Setting Up Remote Debugging.)

In C/C++, the project must be set up to connect using DCOM rather than TCP/IP. To set this property, you must open the <Project> Property Pages dialog box and choose Remote via DCOM for Connection. (For more information, see Project Settings for a C or C++ Debug Configuration.)

By default, the ASP.NET process (aspnet_wp.exe for IIS5.0 and IIS 5.1 on Windows 2000 and Windows XP or w3wp.exe on IIS6 on Windows Server 2003) runs as an ASPNET process. As a result, you must have Administrator privileges on the machine where ASP.NET runs to debug it.

The remote server must grant the debugger access. To grant access to a user, you must add the user to the Administrators group on the server. (If the ASP.NET worker process is running under your the user's own account, you can add the user to either the Administrators group or the Debugger Users group.)

Page 80: Error Handling in ASP

To add a user to the Debugger Users group on a server

1. Log onto the server as Administrator.2. Right-click My Computer and choose Manage from the shortcut menu.

3. Under System Tools, Local Users and Groups, open the Groups folder.

4. Double-click Debugger Users.

5. In the Debugger Users Properties dialog box, you will see a list of members. If the user does not appear in the Members list, click the Add button.

In the Select Users or Groups dialog box, select the name of the user you want to add from the list and click Add.

-or-

a. Type the name of the user in the lower box.b. Click OK.

2. Click OK.

3. You need to restart your computer for the changes to take effect.

For more information about adding users and groups, click the Help button at the top of the Computer Management console.

Error: Error While Trying To Run Project

If you are not a member of Debugger Users on the remote server, you will get the following error message when you try to debug:

Error while trying to run project: Unable to start debugging on the Web server. Access is denied. Check the DCOM configuration settings for the machine debug manager. Would you like to disable future attempts to debug ASP.NET pages for this project.

Debugging a Deployed XML Web Service

Sometimes, you may need to debug an XML Web service that is already deployed and running on a server. To debug a deployed and running XML Web service from Visual Studio .NET, you must attach to the ASP.NET worker process (aspnet_wp.exe for IIS5.0 and IIS 5.1 on Windows 2000 and Windows XP or w3wp.exe on IIS6 on Windows Server 2003). To attach to the ASP.NET worker process, follow the steps in this procedure:

To debug a deployed XML Web service

1. From the Debug menu, choose Processes.

Page 81: Error Handling in ASP

The Processes dialog box appears. For more information, see Processes Dialog Box. The following steps are performed in this dialog box.

2. If the XML Web service is running on a remote server, select the remote machine.3. Select Show System Processes.

4. In the Available Processes list, choose the process aspnet_wp.exe or w3wp.exe.

5. Click the Attach button.

a. In the Attach to Process dialog box, make sure Common Language Runtime is selected in Choose the program types that you want to debug.

b. Click OK.

6. At the bottom of the Processes dialog box is a drop-down list box labeled When debugging is stopped. From this list, you can choose whether to terminate or detach from the process when you stop debugging. The default setting is Detach from this process, which resumes all threads in the process when debugging stops. If you choose Terminate this process, the aspnet_wp.exe or w3wp.xee process terminates when debugging stops. Terminating the aspnet_wp.exe or w3wp.exe process will affect all ASP.NET applications running on the server, so this is not something you want to do in most cases.

7. Click OK.

The next time that the application breaks, a dialog box appears asking for the location of the application's source files. Use this dialog box to locate the source. The filename you specify in the dialog box must match the filename specified in the debug symbols (located on the Web server).

Visual StudioStepping Into an XML Web Service

In Visual Studio .NET, you can step into an XML Web service as though you were stepping into an ordinary function call. Stepping into an XML Web service is possible when both the client and the service are written in managed code (Visual Basic, C#, or Managed Extensions for C++). Stepping occurs automatically across threads, processes, and even machines.

When you step into an XML Web service call, the debugger automatically attaches to the ASP.NET worker process (aspnet_wp.exe for IIS5.0 and IIS 5.1 on Windows 2000 and Windows XP or w3wp.exe on IIS6 on Windows Server 2003). The ASP.NET worker process can be on the local machine or on a remote machine.

Note   To attach to ASP.NET worker process, you must be an Administrator on the server where the process is running. On the client machine, you be in the Debugger Users group or an Administrator. (See Adding Debugger Users.) If the XML Web service is running on the client, you must be an Administrator on the client.

Page 82: Error Handling in ASP

If the ASP.NET worker process is running on an RTM machine, the ASP.NET worker process must run under a user that is a member of Debugger Users on that machine.

If you want to debug both managed and unmanaged code, both types of debugging must be enabled in your project. You can enable unmanaged debugging by choosing the Enable Unmanaged Debugging option in the <Project> Properties dialog box (in the Configuration Properties folder, Debugging category).

When the execution breaks in the XML Web service, you can view a merged callstack that contains calls from both the client and the XML Web service. To see all the information, you may need to enable the display of calls between threads.

To display calls between threads

1. Right-click the Call Stack window.2. From the shortcut menu, choose Include Calls To/From Other Threads.

Once you have stepped into the XML Web service, you can use all the ordinary execution commands such as Step and Continue. At the end of the XML Web service call, you can step out and back into the client that called the XML Web service. When you step out of an XML Web service, the debugger remains attached to the ASP.NET worker process. The debugger detaches from the ASP.NET worker process when you end the debugging session (by choosing Stop Debugging from the Debug menu, for example). You can manually detach the ASP.NET worker process using the Processes dialog box. (For details, see Detaching Programs.)

Visual Studio

ASP.NET Debugging: System Requirements

This topic describes the operating system requirements for debugging ASP.NET Web applications with Visual Studio .NET.

Local debugging is the scenario in which you are trying to debug a Web application on your local (client) machine. In other words, Visual Studio .NET and the Web application are installed and running on the same machine. Local debugging of ASP.NET applications requires Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server, Windows XP Professional, and Windows Server 2003.

Remote debugging is the scenario in which you run Visual Studio .NET on one machine (the client) and debug a Web application running on another machine (the server). Remote debugging of ASP.NET applications requires a local client Windows 2000 or Windows XP (any edition). The remote server must be running Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server, Windows XP Professional, or Windows Server 2003.

For all supported operating systems:

Page 83: Error Handling in ASP

To debug an ASP.NET application, you must be an administrator on the machine that the ASP.NET Web server is running or your name must be in the Debugger Users group if the ASP.NET worker process is running under your user account.

For remote debugging, local and remote machines must be on a domain setup or, if they are on a workgroup setup, both machines must be running Windows 2000 or Windows XP.

To debug the ASP.NET worker process (aspnet_wp.exe or w3wp.exe), you must have permission to debug that process. If the worker process is running as ASPNET (the default), you need Administrator privileges to debug it. For remote debugging, you need Administrator privileges on the remote server machine. On Windows 2000 and Windows XP, you can debug aspnet_wp.exe without Administrator privileges if you edit the machine.config file for the aspnet_wp.exe process so that aspnet_wp.exe runs under your user account rather than ASPNET. On Windows Server 2003, you can use IIS to change the account w3wp.exe runs under.

To run aspnet_wp.exe runs under a user account

1. Open the machine.config file, located on your machine in the CONFIG folder under the path where you installed the runtime.

2. Find the <processModel> section and change the user and password attributes to the name and password of the user account you want aspnet_wp.exe to run under.

3. Save the machine.config file.

4. Find the Temporary ASP.NET Files folder, which should be in the same path as the CONFIG folder. Right-click the Temporary ASP.NET Files folder and choose Properties from the shortcut menu.

5. In the Temporary ASP.NET Files Properties dialog box, choose the Security tab.

6. Click the Advanced button.

7. In the Access Control Settings for Temporary ASP.Net Files dialog box, click the Add button.

8. Enter the user name in the Name box, and then click OK.

9. In the Permission Entry for Temporary ASP.NET Files dialog box, give the user full permissions, and then click OK to close the Temporary ASP.NET Files Properties dialog box.

Windows 2000

You can use Visual Studio .NET on a Windows 2000 client machine to debug ASP.NET applications running locally or on a remote server. The debugging client may be running Windows 2000 Workstation or Workstation Server (with or without Terminal Services). If the client machine is running Windows 2000 Workstation, you must install Microsoft Internet Information Services before debugging.

You can begin ASP.NET debugging by launching an application within a Visual Studio (by choosing a Start or Step command from the Debug menu) or by launching the application

Page 84: Error Handling in ASP

without debugging and using the Processes dialog box to attach to it. For more information, see Attaching to a Running Program or Multiple Programs.

Windows XP and Windows Server 2003

From a client machine running Windows XP Professional or Windows Server 2003, you can debug ASP.NET applications running locally or on a remote server. From a client machine running Windows XP Home Edition, you cannot debug ASP.NET applications.

You can begin ASP.NET debugging by launching an application within a Visual Studio (by choosing a Start or Step command from the Debug menu) or by launching the application without debugging and using the Processes dialog box to attach to it. For more information, see Attaching to a Running Program or Multiple Programs.

Visual Studio

Debugging ASP.NET Web Applications

Debugging an ASP.NET Web application with Visual Studio .NET is similar to debugging a Windows Form or any other Windows application. The fact that application is running on the Web should be mostly transparent to you.

In This SectionDebugging ASP.NET Applications During Development

Provides steps for debugging an ASP.NET application during development. These steps include setting debug mode for the configuration file, setting project properties, starting the debugger, setting and clearing breakpoints, stepping, and ending the debugging session.

Debugging Deployed ASP.NET Applications

Discusses debugging a Web application that is already deployed and running on a server. Information includes considerations and steps for debugging.

Debugging Web Applications on a Remote Server

Lists prerequisites for debugging a Web application on a remote server.

Debugging Client-Side Scripts

Discusses testing scripts and client side scripts in ASP.NET pages. Tasks you can perform when debugging client-side scripts in a Web page include viewing source code, controlling the pace of script execution with breakpoints and stepping, viewing and changing variable and property values, and viewing and controlling script flow with the Call Stack window.

Debugging ASP.NET Web Services

Page 85: Error Handling in ASP

Describes debugging ASP.NET Web services. Information includes debugging an XML Web service on //localhost, debugging an XML Web service on a remote server, and debugging a deployed XML Web service.

ASP.NET Debugging: System Requirements

Describes the operating system requirements for debugging ASP.NET Web applications with Visual Studio .NET.

Debug Mode in ASP.NET Applications

Discusses setting debug mode for an ASP.NET application. Information includes a description of Web.config files, suggestions for editing the file, sample code, and the behavior of hierarchical configuration files.

Global Exception Handling with ASP.NET

Global Exception Handling

You can't debug a problem if you don't know that it exists. After you take your web application live, you are no longer the only one who is using it (hopefully), so you need an effective plan to track exceptions when they occur while others are surfing your site. A great way to do this is to implement an exception handler at the application level. This will allow you to consolidate the logging and notification parts of your exception handling in one convenient place. As you'll see from the code examples that follow, your global exception handler can handle both specific exceptions that you trap in your code and generic unhandled exceptions.

Post a comment Email Article

Print Article

Share Articles

o Digg

Page 86: Error Handling in ASP

o del.icio.us

o Slashdot

o DZone

o Reddit

o StumbleUpon

o Facebook

o FriendFeed

o Furl

o Newsvine

o Google

o LinkedIn

o MySpace

o Technorati

o Twitter

o Windows Live

o YahooBuzz

After your global exception handler has done its work, you'll want to redirect the users of your website to a friendly page that tells them that something has gone wrong, and then provide them with customer support information as well as a link back to your web application's home page.

Implementing the Application_Error Event Handler

The HttpApplication class in the System.Web namespace implements an Error event handler. This should not be confused with the HttpApplicationState class, which contains the definition for the Application object that you use in a typical ASP.NET page. You can implement this event handler in the global.asax file as shown in Listings 1 and 2.

Listing 1: Application_Error Event Handler<%@ Application Language="C#" %><%@ Import Namespace="System.Diagnostics" %>

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

Page 87: Error Handling in ASP

void Application_Error(object sender, EventArgs e){ //get reference to the source of the exception chain Exception ex = Server.GetLastError().GetBaseException();

//log the details of the exception and page state to the //Windows 2000 Event Log EventLog.WriteEntry("Test Web", "MESSAGE: " + ex.Message + "\nSOURCE: " + ex.Source + "\nFORM: " + Request.Form.ToString() + "\nQUERYSTRING: " + Request.QueryString.ToString() + "\nTARGETSITE: " + ex.TargetSite + "\nSTACKTRACE: " + ex.StackTrace, EventLogEntryType.Error);

//Insert optional email notification here...}</script>

Listing 2: Application_Error Event Handler (VB)<%@ Application Language="VB" %><%@ Import Namespace="System.Diagnostics" %>

<script language="VB" runat="server">Sub Application_Error(sender As Object, e As EventArgs) 'get reference to the source of the exception chain Dim ex As Exception = Server.GetLastError().GetBaseException()

'log the details of the exception and page state to the 'Windows 2000 Event Log EventLog.WriteEntry("Test Web", _ "MESSAGE: " & ex.Message & _ "\nSOURCE: " & ex.Source & _ "\nFORM: " & Request.Form.ToString() & _ "\nQUERYSTRING: " & Request.QueryString.ToString() & _ "\nTARGETSITE: " & ex.TargetSite & _ "\nSTACKTRACE: " & ex.StackTrace, _ EventLogEntryType.Error)

'Insert optional email notification here...End Sub</script>

First, you have to be sure to set a reference to the System.Diagnostics namespace. You'll use the EventLog class in this namespace to write exception details to the Windows 2000 event log. Inside the Application_Error event handler, you declare an Exception object and initialize it through a call to Server.GetLastError().GetBaseException().

The GetLastError() method of the Server object simply returns a reference to a generic HttpException. This is a wrapper that was placed around the original exception when it was passed from your ASP.NET page to the Application_Error event. To get access to the original

Page 88: Error Handling in ASP

exception, you need to call its GetBaseException() method. This will yield the original exception information, regardless of how many layers have been added to the exception tree.

Next, you make a call to the WriteEntry() method of the EventLog class. There are several overloaded signatures for this method. The implementation that we chose to use here accepts three parameters. The first parameter is the source of the error. It appears in the Source field of the Windows 2000 event log viewer. The second parameter is the log data itself. You can see that we have added a lot of information to help track down what caused the exception, including the exception message, the exception source, the contents of the Form collection, the contents of the QueryString collection, the name of the method that generated the error (TargetSite), and a complete stack trace.

Note that the stack trace contains the name of the file that was the source of the exception. However, it strips off the contents of the query string—hence the need to specifically include it previously. The third and final parameter to the WriteEntry() method is an enumeration of type EventLogEntryType. We chose to use the Error element of the enumeration.

At the end of the event handler, we inserted a comment block where you can optionally put code to email the exception information to your IT support staff. Discussion of the different messaging paradigms in the .NET framework is beyond the scope of this article.

After the Application_Error event has completed its work, it automatically redirects the user of your web application to your custom error page. Optionally, however, you can use the Server.ClearError() method after you have logged the exception and redirect your user using the Server.Execute() method, specifying the page that you want to load in the user's browser.

The code that you have just implemented will capture all unhandled exceptions that occur in your web application. If you need to do some cleanup in the event of an exception and you implement structured exception handling inside your ASP.NET page, you can still leverage the global exception handler. Listings 3 and 4 present examples of how you would do it.

Listing 3: Throwing a Handled Exception<%@ Page Language="C#" %>

<script language="C#" runat="server">protected void button1_click(object sender, EventArgs e){ try { //do some complex stuff

//generate your fictional exception int x = 1; int y = 0; int z = x / y; } catch(DivideByZeroException ex) {

Page 89: Error Handling in ASP

//put cleanup code here throw(ex); }}</script>

<form runat="server"> <asp:button id="button1" onclick="button1_click" text="click me" runat="server" /></form>

Listing 4: Throwing a Handled Exception (VB)<%@ Page Language="VB" %>

<script language="VB" runat="server">Protected Sub button1_click(sender As Object, e As EventArgs) Try 'do some complex stuff

'generate your fictional exception Dim x As Integer = 1 Dim y As Integer = 0 Dim z As Integer = x / y Catch ex As DivideByZeroException 'put cleanup code here Throw(ex) End TryEnd Sub</script>

<form runat="server"> <asp:button id="button1" onclick="button1_click" text="click me" runat="server" /></form>

The code in these listings defines a web form with a text box and a button. When you click the button, it fires the button1_click event handler. In the event handler, you would do processing as usual. For the purposes of this demonstration, however, you intentionally generate a DivideByZeroException. This takes you to the catch block. Here, you can perform any page-specific cleanup code before calling throw(ex) to pass your exception to the global exception handler to be logged to the Windows 2000 event log.

When the global exception handler is finished logging the error, the defaultredirect attribute that you set in your config.web file (discussed in the next section) takes over, and you are redirected to the error.aspx page to display your friendly message to the user of your web application.

Setting Up the Custom Error Page

The first step in setting up a custom error page is to modify your config.web file to route the users of your web application to a friendly error page if an exception occurs. It helps to boost

Page 90: Error Handling in ASP

users' confidence in your site when it can recover gracefully from the unexpected. Add the code in Listing 5 to the config.web file of your web application.

Listing 5: Adding the <customerrors> Tag to Your Config.web File<configuration> <customerrors mode="On" defaultredirect="error.aspx" /></configuration>

Note that your config.web file might already have a <customerrors> tag, so you might only need to modify the existing one. The mode attribute of the <customerrors> tag has three settings: On, Off, and RemoteOnly. If the mode is On, users will always be redirected to the custom error page specified by the defaultredirect attribute if an unhandled exception occurs. If the mode is Off, the details of any exception that occurs will be shown to the user in the browser. The RemoteOnly mode is a hybrid of the two other modes. If you are browsing your web application while sitting at the web server itself, it behaves like the Off mode. All other browsers of the site will get the behavior of the On mode. If no defaultredirect attribute is set, a default ASP.NET "friendly, yet not so friendly" message will be displayed to the user when exceptions occur.

Next, you need to build the custom error page (error.aspx) referenced in the config.web file. This is just an ordinary ASP.NET page that includes helpful information for the user of your web application if an error occurs. An extremely simple example is the one in Listing 6.

Listing 6: Simple Custom Error Page<html><head><title>My web application: Error page</title></head><body>An unexpected error occurred in the application. Please contact [ccc]customer service at (800)555-5555. Or, you can click [ccc]<a href="home.aspx">here</a> to go back to the homepage. [ccc]Thank you for your patience.</body></html>

Exception handling in C# and ASP .Net

   Exception handling is an in built mechanism in .NET framework to detect and handle run time errors. Exceptions are defined as anomalies that occur during the execution of a program. The .NET framework provides a rich set of standard exceptions that are used during exceptions handling. Exception handling is one of the major feature provide by .NET. There might be various reason to handle exception, this can be

Page 91: Error Handling in ASP

caused due to improper user inputs, improper design logic or system errors. In this scenario if application do not provide a mechanism to handle these anomalies then there might be cases the application may crash. .NET run time environment provide a default mechanism, which terminates the program execution. 

This article provides insight about exception handling on the basis of ASP.NET and C# as code behind. 

ASP.NET Exception Handling

  In ASP.NET exception handling is achieved using the Try ? Catch ? Finally block. All the three are ASP.NET keywords and are used do exception handling. The try block encloses the statements that might throw an exception whereas catch block handles any exception if one exists. The finally block can be used for doing any clean up process. Any general ASP.NET exception forces the application to terminate without allowing the code to continue executing, resulting in an error page. 

try{// Statements that are can cause exception}catch(Type x){// Statements to handle exception}finally{// Statement to clean up }

try-catch-finally block in ASP.NET

<Script runat=server>Public Page_Load(sender As Object, e As EventArgs){try{// Statements that are can cause exception}catch(Type x){// Statements to handle exception}finally{// Statement to clean up }}</Script>

Page 92: Error Handling in ASP

   When an error occurs, we get an instance of exception or possibly a derived, more specialized instanced, such as a NoNullAllowedException when attempting to insert a null value into a SQL table row that does not allow null value.

   Exceptions provide us with detailed information about what occurred; for example stack trace, inner exception details, message, and additional details. 

Unhandled Exceptions:

When some of exceptions are not handled in Try ? Catch ? Finally block of ASP.NET still there are ways provided by the framework facilities for handling the exception through two events:

Page_Error Application_Error 

 

Page and Application Error Event Handlers

   This is very useful in cases where an exception is unexpected and does not occur within the bounds of a Try/Catch/Finally block. These exceptions are usually an indicator that something is substantially wrong with the application. That is, some abnormal exception has occurred and no means are provided to handle exception. In this case there is the option to deal with the error at either the Page or Application level.

   If the exception is dealt at Page level, the details needs to be provided for the Page_Error event:

C# way of implementation is as follows

public void Page_Error(Object sender, EventArgs e) {// Implementation here}

 

   This event is implemented within the Page that the error may occur within. 

   Alternatively, the Application_Error event can be used to handled the above scenario. Unlike the Page_Error event, the Application_Error event is implemented in global.asax and any unhandled exception that occurs within our application raises from this event.

   C# way of implementation is as follows

public void Application_Error(Object sender, EventArgs e) {// Implementation here}

Working with Custom Errors

Page 93: Error Handling in ASP

 The default settings that is available in machine.config is as follows 

<customErrors mode="RemoteOnly"/>

   The mode attribute has three options that can be used for customizing the error: 

RemoteOnly:

   When an unhandled exception occurs, localhost that is where the web pages are placed will see the ASP.NET error page, which includes compilation details and accessibility to the full source. However, remote users ie. the client browser are shown a different ASP.NET error page that simply lets them know an error occurred. No other details are provided. If any custom error page is available then, this page will be displayed to the remote user when any exception occurs. 

On:

The detailed ASP.NET error page is never shown, even to local users. If a custom error page is available, it is displayed. 

Off:

 The detailed ASP.NET error page is always displayed, even if a custom error page exists. 

   In addition to the mode settings, there are several other configuration options for the customErrors section of the configuration. 

defaultRedirect:

  A custom error page that client is redirected to when an error occurs. For example, if a error page designed with name errorPage.aspx, then the following configuration entry in web.config for an ASP.NET application has to made for obtaining the desired results : 

<customErrors mode="On" defaultRedirect=" errorPage.aspx"/>

   Whenever an unhandled exception occurs within our application, the user is redirected to errorPage.aspx, which provides a user-friendly error message. 

Special Case:

 This option provides a special case for the custom error page depending upon the HTTP status code. For example, a custom error page if the request attempts to access a page does not exist (HTTP 404). Following configuration element need to be put that can be nested in <customErrors>, <error> as

<customErrors mode="On" defaultRedirect=" errorPage.aspx"><error statusCode="404" redirect=" errorPage404.aspx"/></customErrors>

Page 94: Error Handling in ASP

   Now, whenever a request is made for a document that cannot be located, we can send the request to a custom page.. 

C# Exception Handling

In C# exception handling is achieved using the try ? catch ? finally block. All the three are C# keywords that are used do exception handling. The try block encloses the statements that might throw an exception whereas catch block handles any exception if one exists. The finally block can be used for doing any clean up process.

try{// Statements that are can cause exception}catch(Type x){// Statements to handle exception}finally{// Statement to clean up }

try-catch-finally block in C#:

  As mentioned earlier any exception that occurs inside the try block, transfers control to the appropriate catch block and later to the finally block. In C#, both catch and finally blocks are optional. The try block can exist either with one or more catch blocks or a finally block or with both catch and finally blocks. 

   In cases when there is no exception inside the try block, the control directly transfers to finally block. So the statements inside the finally block are always executed. C#, exceptions are objects of the type Exception. The Exception base class is used for any exceptions in C#. Some of the standard exceptions derived of Exception class are DivideByZeroExcpetion, ArgumentException etc. 

Example of un-handled exception:

The following program will encounter an exception when executed. At the time of compilation there will be no error caused. In the following code division by zero exception occurs. The division by zero is a runtime anomaly and program terminates with an error message. 

//C#: Exception Un - Handled

using System;class UnHandledException{public static void Main(){int x = 0;int intTemp = 100/x;

Page 95: Error Handling in ASP

Console.WriteLine(intTemp);}} 

   Any un-handled exceptions finds the appropriate block where it is handled, if they are no appropriate blocks then the default .NET runtime will terminate the execution of the entire program.

Example of handled exception:

The above program can be modified in the following manner to track the exception. You can see the usage of standard DivideByZeroException class

//C#: Exception Handling

using System;class HandledException{public static void Main(){int x = 0;int intTemp = 0;try{intTemp = 100/x;Console.WriteLine(?Program terminated before this statement?);}catch(DivideByZeroException de){Console.WriteLine("Division by Zero occurs"); }finally {

Console.WriteLine("Result is {0}", intTemp);}}} 

  In the above example the program ends in an expected way instead of program termination. At the time of exception program control passes from exception point inside the try block and enters catch blocks. As the finally block is present, so the statements inside final block are executed.

Example of exception un handled in catch block

As in C#, the catch block is optional. The following program is perfectly legal in C#. 

//C#: Exception Handling without catch block

Page 96: Error Handling in ASP

using System;class HandledException{public static void Main(){int x = 0;int intTemp = 0;try{intTemp = 100/x;Console.WriteLine("Not executed line");}finally{Console.WriteLine("Inside Finally Block");}Console.WriteLine("Result is {0}", intTemp);}} 

   The above example will produce no exception at the compilation time but the program will terminate due to un handled exception. But the thing that is of great interest to all the is that before the termination of the program the final block is executed. 

Example of Multiple Catch Blocks:

 A try block can throw multiple exceptions, that can handle by using multiple catch blocks. Important point here is that more specialized catch block should come before a generalized one. Otherwise the compiler will show a compilation error. 

//C#: Exception Handling: Multiple catch

using System;class HandledException{public static void Main(){int x = 0;int intTemp = 0;try{intTemp = 100/x;Console.WriteLine("Not executed line");}catch(DivideByZeroException de){Console.WriteLine("DivideByZeroException" );

Page 97: Error Handling in ASP

}catch(Exception ee){Console.WriteLine("Exception" );}finally{Console.WriteLine("Finally Block");}Console.WriteLine("Result is {0}", intTemp);}} 

Example of Catching all Exceptions 

   By providing a catch block without a brackets or arguments, we can catch all exceptions occurred inside a try block. Even we can use a catch block with an Exception type parameter to catch all exceptions happened inside the try block since in C#, all exceptions are directly or indirectly inherited from the Exception class. 

//C#: Exception Handling: Handling all exceptions

using System;class HandledException{public static void Main(){int x = 0;int intTemp = 0;try{intTemp = 100/x;Console.WriteLine("Not executed line");}catch{Console.WriteLine("oException" );}Console.WriteLine("Result is {0}", intTemp);}} 

The following program handles all exception with Exception object. 

//C#: Exception Handling: Handling all exceptions

Page 98: Error Handling in ASP

using System;class HandledException{public static void Main(){int x = 0;int intTemp = 0;try{intTemp = 100/x;Console.WriteLine("Not executed line");}catch(Exception e){Console.WriteLine("oException" );}Console.WriteLine("Result is {0}", intTemp);}} 

Example of Throwing an Exception:

C# provides facility to throw an exception programmatically. The 'throw' keyword is used for doing the same. The general form of throwing an exception is as follows. 

    throw exception_obj; 

For example the following statement throw an ArgumentException explicitly. 

throw new ArgumentException("Exception"); 

//C#: Exception Handling:

using System;class HandledException{public static void Main(){try{throw new DivideByZeroException("Invalid Division");}catch(DivideByZeroException e){Console.WriteLine("Exception" );}Console.WriteLine("Final Statement that is executed");}

Page 99: Error Handling in ASP

 

Standard Exceptions 

Exception are categorised into two types 

a) exceptions generated by an executing program b) exceptions generated by the common language runtime. 

As explained earlier section System.Exception is the base class for all exceptions in C#. Several exception classes inherit from base class including ApplicationException and SystemException. These two classes form the basis for most of the runtime exceptions. Other exceptions are derived directly from System.Exception include IOException, WebException etc. 

The common language runtime throws SystemException. The ApplicationException is thrown by a user program rather than the runtime. The SystemException includes the ExecutionEngineException, StaclOverFlowException etc. It is generally not recommended to catch SystemExceptions also it is not good programming practice to throw SystemExceptions in applications. Following are few of the example of the above stated exception.

System.OutOfMemoryException System.NullReferenceException Syste.InvalidCastException Syste.ArrayTypeMismatchException System.IndexOutOfRangeException System.ArithmeticException System.DevideByZeroException System.OverFlowException 

User-defined Exceptions:

C#, allows to create user defined exception class this class should be derived from Exception base class. So the user-defined exception classes must inherit from either Exception class or one of its standard derived classes. 

//C#: Exception Handling: User defined exceptions

using System;class UserDefinedException : Exception{public MyException(string str){Console.WriteLine("User defined exception");}}class HandledException{public static void Main()

Page 100: Error Handling in ASP

{try{throw new UserDefinedException ("New User Defined Exception");}catch(Exception e){Console.WriteLine("Exception caught here" + e.ToString());}Console.WriteLine("Final Statement that is executed ");}} 

.NET Framework Developer's GuideBest Practices for Handling Exceptions

A well-designed set of error handling code blocks can make a program more robust and less prone to crashing because the application handles such errors. The following list contains suggestions on best practices for handling exceptions:

Know when to set up a try/catch block. For example, you can programmatically check for a condition that is likely to occur without using exception handling. In other situations, using exception handling to catch an error condition is appropriate.

The following example uses an if statement to check whether a connection is closed. You can use this method instead of throwing an exception if the connection is not closed.

[Visual Basic]

If conn.State <> ConnectionState.Closed Then conn.Close() End If[C#] if(conn.State != ConnectionState.Closed) conn.Close();

In the following example, an exception is thrown if the connection is not closed.

[Visual Basic]

Try conn.Close() Catch ex As InvalidOperationException 'Do something with the error or ignore it. End Try[C#]

Page 101: Error Handling in ASP

try { conn.Close(); } catch(InvalidOperationException ex) { //Do something with the error or ignore it. }

The method you choose depends on how often you expect the event to occur. If the event is truly exceptional and is an error (such as an unexpected end-of-file), using exception handling is better because less code is executed in the normal case. If the event happens routinely, using the programmatic method to check for errors is better. In this case, if an exception occurs, the exception will take longer to handle.

Use try/finally blocks around code that can potentially generate an exception and centralize your catch statements in one location. In this way, the try statement generates the exception, the finally statement closes or deallocates resources, and the catch statement handles the exception from a central location.

Always order exceptions in catch blocks from the most specific to the least specific. This technique handles the specific exception before it is passed to a more general catch block.

End exception class names with the word "Exception". For example:

[Visual Basic]

Public Class EmployeeListNotFoundException Inherits Exception[C#]public class MyFileNotFoundException : ApplicationException {}

When creating user-defined exceptions, you must ensure that the metadata for the exceptions is available to code executing remotely, including when exceptions occur across application domains. For example, suppose Application Domain A creates Application Domain B, which executes code that throws an exception. For Application Domain A to properly catch and handle the exception, it must be able to find the assembly containing the exception thrown by Application Domain B. If Application Domain B throws an exception that is contained in an assembly under its application base, but not under Application Domain A's application base, Application Domain A will not be able to find the exception and the common language runtime will throw a FileNotFoundException. To avoid this situation, you can deploy the assembly containing the exception information in two ways:

Put the assembly into a common application base shared by both application domains

- or -

If the domains do not share a common application base, sign the assembly containing the exception information with a strong name and deploy the assembly into the global assembly cache.

Page 102: Error Handling in ASP

In C# and the Managed Extensions for C++, use at least the three common constructors when creating your own exception classes. For an example, see Using User-Defined Exceptions.

In most cases, use the predefined exceptions types. Define new exception types only for programmatic scenarios. Introduce a new exception class to enable a programmer to take a different action in code based on the exception class.

Do not derive user-defined exceptions from the Exception base class. For most applications, derive custom exceptions from the ApplicationException class.

Include a localized description string in every exception. When the user sees an error message, it is derived from the description string of the exception that was thrown, rather than from the exception class.

Use grammatically correct error messages, including ending punctuation. Each sentence in a description string of an exception should end in a period.

Provide Exception properties for programmatic access. Include extra information in an exception (in addition to the description string) only when there is a programmatic scenario where the additional information is useful.

Return null for extremely common error cases. For example, File.Open returns null if the file is not found, but throws an exception if the file is locked.

Design classes so that an exception is never thrown in normal use. For example, a FileStream class exposes another way of determining whether the end of the file has been reached. This avoids the exception that is thrown if you read past the end of the file. The following example shows how to read to the end of the file.

[Visual Basic]

Class FileRead Sub Open() Dim stream As FileStream = File.Open("myfile.txt", FileMode.Open) Dim b As Byte ' ReadByte returns -1 at EOF. While b = stream.ReadByte() <> True ' Do something. End While End SubEnd Class[C#]class FileRead { void Open() { FileStream stream = File.Open("myfile.txt", FileMode.Open); byte b;

// ReadByte returns -1 at EOF. while ((b == stream.ReadByte()) != true) { // Do something.

Page 103: Error Handling in ASP

} }}

Throw an InvalidOperationException if a property set or method call is not appropriate given the object's current state.

Throw an ArgumentException or a class derived from ArgumentException if invalid parameters are passed.

The stack trace begins at the statement where the exception is thrown and ends at the catch statement that catches the exception. Be aware of this fact when deciding where to place a throw statement.

Use exception builder methods. It is common for a class to throw the same exception from different places in its implementation. To avoid excessive code, use helper methods that create the exception and return it. For example:

[Visual Basic]

Class File Private fileName As String Public Function Read(bytes As Integer) As Byte() If Not ReadFile(handle, bytes) Then Throw NewFileIOException() End If End Function 'Read Function NewFileIOException() As FileException Dim description As String = __unknown ' Build localized string, including fileName. Return New FileException(description) ' End Function 'NewFileIOExceptionEnd Class 'File[C#]class File { string fileName; public byte[] Read(int bytes) { if (!ReadFile(handle, bytes)) throw NewFileIOException(); } FileException NewFileIOException() { string description = // Build localized string, including fileName. return new FileException(description); }}

Alternatively, use the exception's constructor to build the exception. This is more appropriate for global exception classes, such as ArgumentException.

Throw exceptions instead of returning an error code or HRESULT.

Page 104: Error Handling in ASP

Clean up intermediate results when throwing an exception. Callers should be able assume that there are no side effects when an exception is thrown from a method.

Exception-handling in ASP.NET

IntroductionLike in other .NET-applications, exception-handling is also available in ASP.NET-applications. There are a few extensions and special features for exception-handling in ASP.NET that will be explained in this article: Predefined error-handlers, custom error-pages and IHttpModules.

Normal exception-handling

Of course your can use the known try/catch/finally-cascade of exception handling in your code:

try{ File.OpenRead( path );}catch( System.IO.FileNotFoundException ex ){ // handle error}finally{ // cleanup}

But in ASP.NET-applications you have got some extended kinds of error-handling-techniques at hand:

Error handlers

You can use predined error-handlers in your aspx-Page or in Global.asax-file. Here you can catch errors that occur in special scopes of your web-application. To get the Exception that occurred, you can use the method GetLastError() of the Server-property.

// Define it in your aspx-page

Page 105: Error Handling in ASP

private void Page_Error(object sender, System.EventArgs e){ Exception ex = Server.GetLastError();}

// Define it in Global.asaxprotected void Application_Error(Object sender, EventArgs e){ Exception ex = Server.GetLastError();}

This is very useful, cause in a lot of cases, your don't want to implement exception-handling for every block in your code where it could occur. An often used scenario is catching your exeption in Application_Error and redirect to a special page, to offer a user-friendly error-page. Therefore you can use the technique above and redirect manually via code, or you can use the ASP.NET-feature explained in the next paragraph.

Custom Error Pages

The redirection to a custom error-page can be coded but it is more handy to do it by configuration. Here is how you can configure it in your web.config:

<customErrors mode="On" defaultRedirect="Error.htm"/>

If an unhandled exception occurs, the user will be redirected to Error.htm, a page that you can define and design as you like. But you can use more detailled configuration for this. On known errors you can navigate to special error pages. An example for this is, when a page the user navigates to does not exist. Then the error 404 occurs and this is how you can tell ASP.NET to go to a special error-page for that:

<customErrors mode="On" defaultRedirect="Error.htm"> <error statusCode="404" redirect="MyErrorPage404.aspx" /></customErrors>

Nice feature, isn't it? If you don't want to declare your error-page globally, you can also define it in the Page-directive of your aspx-file:

<%@ Page language="c#" Codebehind="Errors.aspx.cs"

Page 106: Error Handling in ASP

AutoEventWireup="false" Inherits="TestExceptions.Errors" errorPage="MyErrPage.aspx" %>

Now the user is redirected to the page defined here, but only if an error in this special page occurs.

Error-handling in IHttpModule

Another possiblity to handle errors is in an own IHttpModule. To define it, you have to implement the interface IHttpModule and bind your error-handler in this class:

public class MyErrorModule : IHttpModule{ public MyErrorModule() { }

#region IHttpModule Members

public void Dispose() { }

public void Init(HttpApplication context) { context.Error += new EventHandler(context_Error); }

void context_Error(object sender, EventArgs e) { Exception e = HttpContext.Current.Server.GetLastError();

// handle exception

// Clear the error so that it doesn't occur again in // the Application_Error-handler HttpContext.Current.Server.ClearError(); HttpContext.Current.Response.Redirect("ErrorPage.htm"); }

#endregion}

You also need to configure this HttpModule in your web.config-File:

Page 107: Error Handling in ASP

<httpModules> <add type="MyErrorModule, MyWebApp" name="MyErrorModule "/></httpModules>

So what is the benefit of using an own HttpModule. Well, the name already says it: You have a modularization for your error-handling. You can change your implementation at one place without touching your application-logic and you can change the errorhandling of your appliation by defining another HttpModule and configuring it in your web.app.

Custom Error Handling in ASP.NET

Introduction

Structured exception handling is a fundamental part of the CLR and provides .Net programmers a great way of managing errors. In addition to CLR exception system, ASP.Net also provides ways of handling errors.

When a runtime or design-time error occurs in an application, ASP.Net shows a default error page that gives a brief description of the error along with the line number on which the error occurred. A developer would wish to view this default error page, during the testing of the application since the description helps him in rectifying the error. But he would never want a user trying to access his application, to view this error page. The user would be least bothered to know about the error. Instead of showing the default error page, it would be more sensible to show a customized error page that would let the user send notification of the error to the administrator.

Explanation

Consider an example of an ASP.Net application that generates an error intentionally to show how ASP.Net detects it and shows the default error page. The below given webform contains a label and a button server control. In the eventhandler for the button click event, the user will be redirected to another webform "Trial.aspx". Since the page being redirected to, is missing ASP.Net will show the default error page indicating it is a runtime error.

Unlike classic ASP, ASP.Net separates the code for the business logic from the content (i.e HTML and interface logic). The sample application has two files named "webform1.aspx" containing the content and "webform1.aspx.vb" containing the code.

WebForm1.aspx

<%@ Page Language="vb" AutoEventWireup="false"Codebehind="WebForm1.aspx.vb" Inherits="ErrorSample.WebForm1"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><title></title><meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"><meta name="CODE_LANGUAGE" content="Visual Basic 7.0"><meta name="vs_defaultClientScript" content="JavaScript"><meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"></HEAD>

Page 108: Error Handling in ASP

<body MS_POSITIONING="GridLayout"><form id="Form1" method="post" runat="server"><asp:Label id="Message" style="Z-INDEX: 101; LEFT: 34px;POSITION: absolute; TOP: 46px" runat="server"></asp:Label><asp:Button id="ErrorButton" style="Z-INDEX: 102; LEFT: 268px;POSITION: absolute; TOP: 41px" runat="server" Text="GenerateError"></asp:Button></form></body></HTML>

WebForm1.aspx.vb

Public Class WebForm1Inherits System.Web.UI.PageProtected WithEvents Message As System.Web.UI.WebControls.LabelProtected WithEvents ErrorButton As System.Web.UI.WebControls.ButtonPrivate Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)Handles MyBase.LoadMessage.Text = "This sample page generates an Error..."End SubPublic Sub ErrorButton_Click(ByVal sender As Object, ByVal e AsSystem.EventArgs)Handles ErrorButton.ClickResponse.Redirect("Trial.aspx")End SubEnd Class

Now if you try to run the above web form by viewing it on the browser, you will get the below shown web page:

Now if you click on the button labeled "Generate Error", you will get the below shown default ASP.Net error page.

Page 109: Error Handling in ASP

Customizing Error Page

To customize the default error page, one will have to change the default configuration settings of the application.

There are three error modes in which an ASP.Net application can work:

1. Off Mode 2. On Mode

3. RemoteOnly Mode

The Error mode attribute determines whether or not an ASP.Net error message is displayed. By default, the mode value is set to "RemoteOnly".

Off ModeWhen the error attribute is set to "Off", ASP.Net uses its default error page for both local and remote users in case of an error.

On ModeIn case of "On" Mode, ASP.Net uses user-defined custom error page instead of its default error page for both local and remote users. If a custom error page is not specified, ASP.Net shows the error page describing how to enable remote viewing of errors.

RemoteOnlyASP.Net error page is shown only to local users. Remote requests will first check the configuration settings for the custom error page or finally show an IIS error.

Page 110: Error Handling in ASP

Configuration File

Customization of error page can be implemented by adding a value for an attribute "defaultRedirect" in the <customErrors> tag of the configuration file "web.config". This file determines configuration settings for the underlying application.

Off ModeIn this scenario, set the mode attribute value to "Off" as shown below:

Web.Config File

<?xml version="1.0" encoding="utf-8" ?><configuration><system.web><customErrors mode="Off" /></system.web></configuration>

When the sample ASP.Net web page is viewed in the browser from the remote machine, one gets the below shown default error page.

The above example thus shows that, whether it is local or remote access, ASP.Net error page is shown.

On Mode

In this scenario, set the mode attribute value to "On" as shown below:

Page 111: Error Handling in ASP

Web.Config File<?xml version="1.0" encoding="utf-8" ?><configuration><system.web><customErrors defaultRedirect="error.htm" mode="On" /></system.web></configuration>

As shown in the configuration file, the "defaultRedirect" attribute has been set to a user-defined page "error.htm". The user-defined error page can be an ASP.Net web page, classic ASP page or a simple HTML page.

For example, the contents of the user-defined error page "error.htm" can be given as follows:

Error.htm

<HTML><BODY><b>We are very sorry for the inconvenience caused to you...<br></b></BODY></HTML>

When the sample ASP.Net web page is viewed in the browser from the remote/local machine, one gets the below shown custom error page.

Page 112: Error Handling in ASP

RemoteOnly Mode

In this scenario, set the mode attribute value to "RemoteOnly" as shown below:

Web.Config File<?xml version="1.0" encoding="utf-8" ?>configuration><system.web><customErrors defaultRedirect="error.htm" mode="RemoteOnly" /></system.web></configuration>

Since the "defaultRedirect" attribute has been set, if the page is requested from a remote machine page is redirected to "error.htm" and if the page is requested from the local machine the default error page is shown.

Notification of Error to the Administrator

In a practical web application, customization of error pages is not the only requirement. The error, if encountered, should be reported to the administrator so that it can be rectified thus enabling subsequent requests to work properly without any error.

Notification of the error can be sent to the administrator in one of the following two ways:

Page 113: Error Handling in ASP

1. Error can be registered as a log entry in the Windows Event Log on the administrator's machine.

2. An Email can be sent to the administrator with a suitable error message.

Writing to the Event Log

In ASP.Net, error can be handled programmatically by writing appropriate code in the page-level error event, for errors on an individual page or in the application-level error event for handling errors that may occur in any page of the application.

Therefore, code for writing in the Event Log should be written in either of the events, depending on the requirement of the application. To illustrate this example, I have written the code in the application-level event with the error mode set to "RemoteOnly" and the "defaultRedirect" attribute to "error.htm". The application-level error event should be included in the global file "global.asax" within the same application folder.

The contents of the global file can be given as follows:

Writing Log Entry in the Event Log

Imports System.WebImports System.Web.SessionStateImports System.DiagnosticsPublic Class GlobalInherits System.Web.HttpApplicationSub Application_Error(ByVal sender As Object, ByVal e As EventArgs)Dim ErrorDescription As String = Server.GetLastError.ToString'Creation of event log if it does not exist Dim EventLogName As String = "ErrorSample"If (Not EventLog.SourceExists(EventLogName)) ThenEventLog.CreateEventSource(EventLogName, EventLogName)End If' Inserting into event logDim Log As New EventLogLog.Source = EventLogNameLog.WriteEntry(ErrorDescription, EventLogEntryType.Error)End SubEnd Class

Event Log support is provided in .Net through the namespace "System.Diagnostics". So, for the above code to work, it is very essential to add a reference to the above-mentioned namespace in the project. In the event handler for application-level error, a log named "ErrorSample" is created if it does not exist in the Event Log. If it already exists, the error entry is added to the existing list of events. After viewing the page on the browser from a remote machine, the event will get listed in the Event Log on the administrator's machine as shown below:

Page 114: Error Handling in ASP

Description of the error can be viewed by selecting the appropriate event and double clicking it. Another form pops up as shown below:

Sending an Email to the Administrator

To illustrate this example, I have written the code for sending an Email to the administrator in the application-level error event. The contents of the global file can

Page 115: Error Handling in ASP

be given as follows:

Sending Email To the Administrator

Imports System.WebImports System.Web.SessionStateImports System.Web.MailPublic Class GlobalInherits System.Web.HttpApplicationSub Application_Error(ByVal sender As Object, ByVal e As EventArgs)Dim mail As New MailMessageDim ErrorMessage = "The error description is as follows : "& Server.GetLastError.ToStringmail.To = [email protected] = "Error in the Site"mail.Priority = MailPriority.Highmail.BodyFormat = MailFormat.Textmail.Body = ErrorMessageSmtpMail.Send(mail)End SubEnd Class

In the above code, SMTP service is being used to send the mail across. SMTP mail service support is provided in .Net through the namespace "System.Web.Mail". So, for the above code to work, it is very essential to add a reference to the above-mentioned namespace in the project.

Exception Handling Techniques in ASP.NET

Introduction

Exceptions or errors are unusual occurrences that happen within the logic of an application. You cannot program for every possibility; hence, they are imminent. If an exception occurs within an application, the user is presented with a yellow page that looks ugly. So, how do you deal with these situations? You use exception handling techniques in ASP.NET.

Background

There are three ways to handle exceptions/errors in ASP.NET:

1. try-catch block. This is also called Structured Exception Handling (SEH).2. Error Events.

3. Custom Error Page.

You will look at each one of them in detail in the next sections.

try-catch Block

Enclose code that accesses files, databases, and so forth inside a try-catch block because access to those resources might be denied due to various reasons causing an exception. The third part of

Page 116: Error Handling in ASP

this block is finally. It is executed irrespective of the fact that an exception has been raised. Hence, use the finally block to complete the housekeeping jobs.

As a good programming practice, always catch specific exceptions. To view the exception types supported by the .NET Framework, use the Debug menu and select Exceptions in Visual Studio.NET.

In the following code, you try to access a table that does not exist in the Northwind database; therefore, an exception is raised. By using the try catch and finally block, you handle the exception and display a message.

try{ con = new SqlConnection("integrated security=SSPI; data source= (local);persist security info=False; initial catalog=Northwind"); da = new SqlDataAdapter("Select * from TblNotExisits", con); ds = new DataSet(); da.Fill(ds);}catch(SqlException ex){ return "Connection Unsuccessful " + ex.Message;}finally{ con.Dispose();}return "Connection Successful";

Using Error Events

There are three different error events in ASP.NET that can be used in conjunction with SEH so that all exceptions are handled and the user is presented with a user-friendly error message.

1. Page_Error: Occurs when an error occurs within the Web page. This event is in the Web form.

2. Global_Error: Occurs when an error occurs within the application. This event is in the Gloabl.asax file.

3. Application_Error: Occurs when an error occurs within the application. This event is in the Gloabl.asax file.

Methods in the Server object are used to handle the exception in the error events.

1. GetLastError: Gets the last exception that occurred on the server.2. ClearError: Use this method to handle the exception and stop the error to trigger the

subsequent error event or display the error to the user.

Page 117: Error Handling in ASP

In the following code, you handle the exception in all the above three mentioned events but call the ClearError method only in the Application_Error event so that the error is propogated to the above level.

private void Page_Error(object sender, System.EventArgs e){ Exception ex = Server.GetLastError(); Response.Write("Handled error from Page<br>"); //Server.ClearError();}protected void Application_Error(Object sender, EventArgs e){ Exception ex = Server.GetLastError(); Response.Write("Handled error from Application <br>"); Server.ClearError();}protected void Global_Error(Object sender, EventArgs e){ Exception ex = Server.GetLastError(); Response.Write("Handled error from Global <br>"); }

Using Custom Error Pages

Use custom error page to handle HTTP exceptions such as page not found, unauthorized access, and so forth. You can specify custom error pages in two places:

1. customErrors section of the web.config file. This setting specifies the application-wide error page to display for unhandled HTTP errors. HTTP errors are identified by the HTTP status code. Include the <error> tag in the customErrors to display a status code-specific error page. Does not work with .htm or .html files. Set the mode attribute to "On" to view the error page locally.

2. errorPage attribute of the @Page directive of the Web form to display the error page for the error generated on the particular Web form.

The customsError section in the web.config file specifies the application to redirect to Error404.aspx file if a non-existent file is requested.

<customErrors mode="On" defaultRedirect="Error.aspx"> <error statusCode="404" redirect="Error404.aspx" /></customErrors>

The @Page directive specifies the error page to be redirected to if an error occurs in the Web page.

<%@ Page language="c#" Codebehind="PageErr.aspx.cs" AutoEventWireup="false" Inherits="ExceptionHandling.PageErr" errorPage="Error.aspx" %>

Page 118: Error Handling in ASP