Error Handling in ASP
Error Handling in ASP
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).
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:
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.
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.
Gets a string representation of the frames on the call stack at the time the current
StackTrace
exception was thrown.
TargetSite Gets the method that throws the current exception.
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'.
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()
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:
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
As mentioned earlier, via the ApplicationException class you have the ability to create your own
exception types.
Imports System
Imports System.Text
Namespace CustomExceptions
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
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:
WebForm1.aspx.vb
Imports article_error_handling.CustomExceptions
Inherits System.Web.UI.Page
End Class
This (admittedly simple) example you can extend to your own requirements.
Two facets:
1. Page redirection
2. Using the Page objects error event to capture exceptions
Taking each in turn:
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:
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.
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:
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.
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:
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:
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>
<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.NET
Complete Example for Error Handlers
• Web.config
• Global.asax
• Default.aspx
• ExceptionUtility (to be put in the App_Code folder)
• GenericErrorPage.aspx
• HttpErrorPage.aspx
• 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" />
</system.web>
</configuration>
Global.asax
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,"
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
' 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))
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 System
Imports System.IO
Imports System.Web
' 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
// 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
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();
}
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
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
</script>
<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();
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" %>
<script runat="server">
Dim ex As Exception = Nothing
</script>
<script runat="server">
protected Exception ex = null;
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
</script>
<script runat="server">
protected HttpException ex = null;
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
</script>
<script runat="server">
protected HttpException ex = null;
DefaultRedirectErrorPage.aspx
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
</script>
<script runat="server">
protected HttpException ex = null;
ASP.NET
How to: Handle Application-Level Errors
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
' 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))
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.NET
How 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.
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
ASP.NET
ASP.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 Overview
Using the Debugger with Web Pages
What's New in the Visual Studio Debugger
How to: Set Up Remote Debugging
Debugging ASP.NET and AJAX Applications
ASP.NET
ASP.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.
• 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.
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.
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.
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.
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.
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.
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.
If the Web server is on another computer (a remote server), you must ensure that the computer is
configured properly. This involves:
• 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.
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.
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:
There are two different scopes where we could specify which page the user should be redirected
to, when errors go unhandled:
Page Level
This attribute defines the page the user should be redirected to when an unhandled exception
occurs in that specific page. For example,
Collapse
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
Collapse
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.
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
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
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.
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();
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
Exception ex = Server.GetLastError();
this.ErrorPage = "/ErrorHandling/ErrorPages/BaseError.html";
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
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.
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.
All the points we saw in the Page and Application handlers apply to the Module handler as well.
Important Notes
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.
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.NET
Using 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.
In This Section
Attaching to Running Processes
Debugging Basics: Breakpoints
Execution Control
Viewing Data in the Debugger
Table legend:
Applies
Does not apply
Command 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:
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:
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.
Table legend:
Applies
Does not apply
Command 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
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 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
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.
Table legend:
Applies
Does not apply
Command 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:
Table legend:
Applies
Does not apply
Command 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
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.
The following debugger windows offer important information about your program.
To view Try
How to: Use the Registers
Register contents
Window
Memory contents How to: Use the Memory Window
• Names of functions on the call stack
• Parameter types How to: Use the Call Stack
Window
• Parameter values
How to: Use the Disassembly
Assembly code generated by the compiler for your program
Window
Threads — sequential streams of execution — created by your
How to: Use the Threads Window
program
Modules (DLLs and EXEs) used by your program How to: Use the Modules Window
Note:
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.
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.
• You can now step into .NET Framework source code when debugging. For more
information, see How to: Debug .NET Framework Source.
The Visual Studio 2008 debugger has been enhanced by the addition of the following features:
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.
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.
You can debug LINQ queries, including LINQ to SQL Queries. For more information,
see Debugging LINQ.
Table legend:
Applies
Does not apply
Command or commands hidden by default
• 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:
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.
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:
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.
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.
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.
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 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.
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.
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.
• Setting breakpoints.
• Invoking debugger from a Web Forms page in a file system Web site.
Prerequisites
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.
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.
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.
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.
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.
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
ID: CaptionLabel
Label
Text: (empty)
ID: NumberTextBox
TextBox
Text: (empty)
ID: SquareButton
Button
Text: Square
ID: ResultLabel
Label
Text: (empty)
Note:
For this walkthrough, the layout of the page is not important.
Visual Basic
C#
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.
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
C#
if(Page.IsPostBack == false)
{
CaptionLabel.Text = "Enter a number: ";
}
else {
CaptionLabel.Text = "Enter another number: " ;
}
Note that the result is incorrect, because there is a bug in the program. The correct result
is 9.
4. Close the browser.
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.
To set breakpoints
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.
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.
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.
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.
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
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).
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"
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.
Because the code is not currently running (the page has finished processing), you are in
edit mode and can make permanent changes.
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.
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.
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:
In This Section
Preparing to Debug ASP.NET
Describes the steps that are required to enable debugging of ASP.NET applications.
Table legend:
Applies
Does not apply
Command 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.
Explains limits about how to debug WCF Web applications by using Visual Studio.
Discusses special configuration steps needed for debugging system requirements for
debugging ASP.NET on Windows Server 2003.
Describes steps for debugging a WCF service that is not hosted on IIS or the ASP.NET
Development Server.
Table legend:
Applies
Does not apply
Command 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.
Table legend:
Applies
Does not apply
Command 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
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.
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 —
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.
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.
Table legend:
Applies
Does not apply
Command 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:
For more information, see Project Settings for a C or C++ Debug Configuration.
Table legend:
Applies
Does not apply
Command 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.
1. In Solution Explorer, right-click the name of a Web project and select Property Pages.
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.
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.
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.
In This Section
How to: Debug Web Applications and Web Services
Explains how to deal with exceptions that occur while you debug ASP.NET applications.
Table legend:
Applies
Does not apply
Command 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.
• 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.
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.
3. On the Debug menu, click Stop Debugging to end the debugging session, or, on the File
menu in Internet Explorer, click Close.
4. Visual Studio Debugger
5. Debugging Deployed Web Applications and Web Services
6. This topic applies to:
Edition Visual Basic C# C++ Web Developer
Express
Standard
Pro and Team
7. Table legend:
Applies
Does not apply
Command 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 Studio
Debugging 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.
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).
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.
• 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.
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.
</script>
</head>
<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>
c:\inetput\wwwroot
http://localhost/cookie.html
To manually attach
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
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.
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.
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.
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
There are several ways that you can debug the client-side script in your application:
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.
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.
From now on, when any script is executed, the debugger stops at the first statement of the
script.
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 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:
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.
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.
-or-
For more information about adding users and groups, click the Help button at the top of the
Computer Management console.
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.
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:
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 Studio
Stepping 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.
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.
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.
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
without debugging and using the Processes dialog box to attach to it. For more information, see
Attaching to a Running Program or Multiple Programs.
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 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 Section
Debugging 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.
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.
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
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.
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
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.
<form runat="server">
<asp:button id="button1" onclick="button1_click"
text="click me" runat="server" />
</form>
<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.
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
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.
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.
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
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.
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
}
<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>
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
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:
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.
<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 :
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
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
}
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.
using System;
class UnHandledException
{
public static void Main()
{
int x = 0;
int intTemp = 100/x;
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.
The above program can be modified in the following manner to track the exception. You can see the
usage of standard DivideByZeroException class
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
{
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.
As in C#, the catch block is optional. The following program is perfectly legal in C#.
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.
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.
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" );
}
catch(Exception ee)
{
Console.WriteLine("Exception" );
}
finally
{
Console.WriteLine("Finally Block");
}
Console.WriteLine("Result is {0}", intTemp);
}
}
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.
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);
}
}
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);
}
}
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;
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");
}
}
Standard Exceptions
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.
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]
[Visual Basic]
Try
conn.Close()
Catch ex As InvalidOperationException
'Do something with the error or ignore it.
End Try
[C#]
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]
• 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.
• 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
[Visual Basic]
Class File
Private fileName As String
Exception-handling in ASP.NET
Introduction
Like 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
try
{
File.OpenRead( path );
}
catch( System.IO.FileNotFoundException ex )
{
// handle error
}
finally
{
// cleanup
}
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 Global.asax
protected 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.
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:
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:
// handle exception
#endregion
}
<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.
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
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
WebForm1.aspx.vb
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.
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 Mode
When 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 Mode
In 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.
• RemoteOnly
ASP.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.
Configuration File
• Off Mode
In this scenario, set the mode attribute value to "Off" as shown below:
Web.Config File
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:
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.
• 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:
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.
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.
Imports System.Web
Imports System.Web.SessionState
Imports System.Diagnostics
Public Class Global
Inherits System.Web.HttpApplication
Sub 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)) Then
EventLog.CreateEventSource(EventLogName, EventLogName)
End If
' Inserting into event log
Dim Log As New EventLog
Log.Source = EventLogName
Log.WriteEntry(ErrorDescription, EventLogEntryType.Error)
End Sub
End Class
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
be given as follows:
Imports System.Web
Imports System.Web.SessionState
Imports System.Web.Mail
Public Class Global
Inherits System.Web.HttpApplication
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim mail As New MailMessage
Dim ErrorMessage = "The error description is as follows : "
& Server.GetLastError.ToStringmail.To = [email protected]
mail.Subject = "Error in the Site"
mail.Priority = MailPriority.High
mail.BodyFormat = MailFormat.Text
mail.Body = ErrorMessage
SmtpMail.Send(mail)
End Sub
End 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.
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
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
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";
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.
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.
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.
The @Page directive specifies the error page to be redirected to if an error occurs in the Web
page.