Debugging an ASP.NET Web Application, Part II - Debugging...
Bugs are a fact of the programmer's life. How can we deal with them efficiently? In this series of two articles
I'm going to look at two main areas of finding and fixing errors in your program - Tracing and Debugging.
By: Chris Sully
Date: July 2, 2003
Download the code.
Introduction
Bugs are a fact of the programmer's life. This is the second of two articles examining how we may deal with them
efficiently within .NET. In part I we looked at the process of collecting information about a programs execution
(tracing). Tracing is really a part of the overall activity of debugging: finding and fixing errors in your
program. In part II of this series we'll focus on debugging and in particular on the tools available to the
programmer to simplify the task.
Debugging
Debugging is the process of finding and fixing errors in your application. Without good tools this process can be
time consuming. VS.NET comes with a large toolset in this area that we shall consider in this article. I should
also point out at this point that the .NET framework ships with a GUI debugger located in
\Program Files\Microsoft.NET\FrameworkSDK\GuiDebug\DbgCLR.exe which is rather similar to the VS.NET tool so all
is not lost if you do not have a copy of VS.NET. Thus much of what is presented below applies equally to DbgCLR.exe
though some of the interface detail may differ slightly. The VS.NET debugger does offer additional features
however, as well as offering the advantage of being integrated with the rest of the IDE toolset.
Firstly we should differentiate between two types of errors:
- Compile time errors: these are largely syntactic errors which will be captured by the compiler. Note, that
use of Option Explicit and Option Strict can reduce the likelihood of runtime errors via compile time
identification of likely issues. See my article on Error Handling in ASP.NET for more information.
- Runtime errors: these are bugs � programs that compile successfully but do not behave as expected.
In part I of this article we have already come across setting of the configuration mode of the application in
VS.NET and the ability to differentiate between Release and Debug modes, the latter being the default.
Debug mode may be set explicitly within the web.config file via the compilation element as follows:
|
<compilation debug="true" />
|
as well as at the Page level via the debug attribute of the Page directive.
Setting Breakpoints and Stepping Through Program Execution
Stepping is the step-by-step execution of a program. This allows the developer to track the logic of the program
execution to see where it might be going wrong. As part of this facility you are able to monitor the state of
application objects (e.g. variables, database table values, etc.) before and after each step to check whether the
program is correctly affecting them.
The steps of the stepping process are definable by the developer. The debug menu of VS.NET provides three options
for step execution:
Step Into: executes the code in step mode � if a method call is encountered the program execution steps
into the code in step mode.
Step Over: will not execute the next method call in step mode, continuing to the next statement after the
method call.
Step Out: if already in a method call will continue through the rest of the method without stepping,
returning to step mode when control returns to the calling statement.
You may also break program execution on identified breakpoints which allows you to do further analysis on the
program state at that point of execution. Typically, you will run the program to a breakpoint, which is a point
prior to that which you have identified for possible concern, and step through the subsequent code to check that
the code is working as it should.
As well as adding a breakpoint you can remove or disable it. Disabling has the advantage of leaving the breakpoint
for possible subsequent use whilst removing its effect for the moment. When you add a new breakpoint you have a
variety of options and facilities at your disposal. The breakpoint window is also accessible via the debug menu
from which you may manage your breakpoints, locate the breakpoint in code as well as view the corresponding
disassembled code.
I'd suggest at this point you open up a web form which uses some code behind and try setting a few breakpoints,
start the page with debugging from the debug menu and try stepping though the code. Or you may prefer to wait for
the example of the next section.
Further .NET debugging tools: Watch, Autos, Locals, Me, Immediate, and the Call Stack Windows
As you can see from this list you have a variety of other tools available to you as a VS.NET developer to analyse
the program state at the breakpoint, as follows:
Watch
The Watch window allows you to add 'watches' to particularly variables and expression for continuous monitoring.
Thus when you set up a watch whenever you return to the IDE while debugging you will see the current value of the
variable or expression defined by the watch.
Autos
The autos window (automatically) displays the variables in the current statement and the previous statement.
Locals
Displays the variables local to the current context, i.e. the current method under execution
Me
The Me window allows you to examine members associated with the current object � typically a web form for an
ASP.NET application, but not necessarily. It also allows you to change these values.
Immediate
The immediate window allows (immediate) access to the values of variables and expressions while debugging, at the
breakpoint.
Call Stack
The Call Stack window shows you the method call stack thus providing information about the path taken by the code
to reach its current point of execution.
An Example
Let's run through an example. Put together a quick web form with a textbox of id tbNumber, a button labelled
'Calculate' or similar and another textbox for output named tbfactorial. Add the following code to the button's
click event:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim intNumber, intFactorial As Integer
Try
intNumber = Convert.ToInt32(tbNumber.Text)
intFactorial = factorial(intNumber)
tbfactorial.Text = intFactorial.ToString()
Catch ex As Exception
debug.writeline(ex.Message)
End Try
End Sub
|
and add code in the same class for the factorial function:
Private Function factorial(ByVal intNumber As Integer) As Integer
Dim intFac As Integer = 1
Dim i As Integer
For i = 2 To intNumber
intFac = intFac * i
Next
Return intFac
End Function
|
Remembering also to add:
|
Imports System.Diagnostics
|
to the codebehind file.
Firstly start the application from the debug menu and see what it does. Try entering textual input and see what
happens. Check the content of the output window (view � other windows). You should see the debug information
displayed via the try ... catch block when you inputted the textual data.
Set a break point near the start of the factorial function and run the page.
Try the windows of the debug menu to see what they will display. Add a watch window and add a watch for the
intFac variable. Step into the code and see how the reported value of the variable changes. Similarly
open the locals, auto, me, immediate and call stack windows and see how their contents change. Explore each. Two
are worthy of further comment:
In the immediate window prefix variable names / expressions with ? to obtain a response, e.g.
?intFactorial. You may also call functions, e.g.
Factorial(intNumber).
In the call stack window the currently executing method is at the top of the stack pointed by a yellow arrow. When
this method is exited, the next entry in the stack will be the method receiving the control of execution.
Debugging on exceptions
You can also control the way the VS.NET debugger behaves when it encounters a line of code that throws an
exception. This is achieved via the Exceptions dialog box (Debug-Exceptions). This allows specification of the
debugger's behaviour for each type of exception defined in the system, including programmer defined exceptions if
you so desire. Behaviour is controllable on two levels:
- when the exception is thrown
- if the exception is not handled
Debugging a running process
Up until this point we have assumed that the application we are running is doing so within the VS.NET environment
by starting them within this environment. VS.NET also allows you to debug processes running outside the debugging
environment � handy for debugging already deployed applications, e.g. applications in staging environments. This
kind of thing often proved problematic with previous versions of VS.
When a web page is served from the web server, the ASP.NET worker process (aspnet_wp.exe) serves the request. To
debug a running page you need to attach the VS.NET debugger to the aspnet_wp.exe process running on the web server.
Additionally, you need to open the corresponding source files in VS.NET and set your breakpoint at a suitable
location. Now when you interact with the already running web page it will break into the debugger whenever the
break point is hit.
The actual steps needed to achieve the above are:
- Launch the page in Internet Explorer.
- VS.NET Tools � Debug Processes. Change the name field to point to the web server specified in 1, making sure
you check the 'Show system processes' option. In the available processes list you want to attach to aspnet_wp.exe.
Selecting attach will bring up an 'attach to process' dialog box � select the CLR option and click OK.
- Open the corresponding source file in VS.NET.
A couple of important points:
- Don't debug on production servers � attaching a debugger to an aspnet_wp.exe on a production server will freeze
the execution of all other applications / user application instances on that server.
- Similarly don't terminate the aspnet_wp.exe process after debugging is complete as it will affect all other
applications / users on that server.
Debugging a remote process
This is similar to debugging a running process. The difference is you are effectively debugging on the remote
machine. The extra step required is that prior to when selecting a running process from the Processes dialog box
you must select the remote machine name from the name list.
Further, before you can debug remotely you must perform a one time configuration of the remote machine where the
processes are running achievable via either installing VS.NET on the remote machine or installing the remote
components setup on the remote machine (VS.NET setup disk 1).
This will ensure that the machine debug manager (mdm.exe) is on the remote computer. This runs as a background
service providing debugging support. The logged in user at time of installation will also be added to the Debug
users group � a further requirement for this to work. This process will also configure SQLServer for Stored
Procedure debugging if SQLServer exists on the server.
For further information see 'setting up remote debugging' in VS.NET help
Debugging Code in DLL Files
The process of debugging a DLL file for which you have the source code is similar to debugging a web form with one
main difference: the code in a DLL cannot be called directly so you need a client (web form) to call it. This makes
the typical process as follows:
- Launch the web form that uses the members of the DLL.
- Launch VS.NET and attach the debugger to the web form. Set a breakpoint where the method in the DLL file is
called. Continue with execution.
- Execution will break at the breakpoint and you can step into the DLL code from the Debug menu.
Debugging Client-side Scripts
Again this works similarly to web forms with the proviso that client-side debugging only works with IE. You have
to enable script debugging in IE (Tools-Internet Options-Advanced and uncheck Disable script debugging in the
browsing section).
You can then attach the debugger to the iexplore.exe process displaying the web form. This is only required if you
are debugging an already running process. When attaching to the process in the Attach to Process dialog box you
must make sure you select the script option.
Debugging SQLServer Stored Procedures
You can even perform debugging of stored procedures in the VS.NET environment and here is a brief overview of how
to achieve this:
You need to enable SQLServer debugging for your solution. The option for this is located via Solution-Properties
� Configuration properties � Debugging. I'll assume you have a project that uses stored procedures as the interface
between data store and web form already. Set a breakpoint in your web form code before you call the stored
procedure. In Server Explorer navigate to the stored procedure in question, right click and select edit. Insert a
breakpoint in the first line of code.
Run the project; execution will break at the breakpoint in the web form. Select 'step into' until the stored
procedure is called and you will be able to step through the stored procedure code as well. Investigate how you
can still use the watch and locals windows to examine variables.
This ability is a boon to developers needing to debug complex stored procedures.
Conclusion
I hope the two articles in this series have provided a reasonable introduction to debugging your ASP.NET
applications. Part I focused on the support for tracing in.NET and part II on debugging tools and techniques. If
there are any aspects of these articles, or any other on DotNetJohn for that matter, that you would like me to
look at in further detail email me sullyc-olops@btinternet.com
or DotNetJohn.
References
ASP.NET: Tips, Tutorial and Code
Scott Mitchell et al.
Sams
Developing and implementing web applications with VB.Net and VS.Net
Mike Gunderloy
Que
.NET SDK documentation
You may download the test program here.