debugging an asp

27
Debugging an ASP.NET Web Application, Part I - Tracing... 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: May 31, 2003 Printer Friendly Version Introduction Bugs are a fact of the programmer’s life. How can we deal with them efficiently? In this series of 2 articles I’m going to look at two main areas in order to address this question: 1. Tracing: the process of collecting information about a program’s execution and 2. Debugging: the overlapping topic of finding and fixing errors in your program We shall look both at the inherent supporting features provided by the .NET framework and ASP.NET and the additional tools provided by VS.NET over the course of the two articles. Part I shall focus on Tracing, Part II on Debugging, though as I’ve already stated these are overlapping areas as you shall see. Tracing Tracing is the ability of an application to generate information about its own execution. The idea is that subsequent analysis of this information may help us understand why a part of the application is not behaving as it should and allow identification of the source of the error. We shall look at two different ways of implementing tracing in .NET 1. via the System.Web.TraceContext class 2. via the System.Diagnostics.Trace and System.Diagnostics.Debug classes Tracing can be thought of as a better (more featureful and automated) alternative to the response.writes you used to put in your old ASP3.0 code to help debug pages! System.Web.TraceContext The TraceContext class is responsible for gathering the execution details of a web request. The TraceContext object for the current request can be accessed through the Trace property of the Page

Upload: pavankurella

Post on 12-Nov-2014

811 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Debugging an ASP

Debugging an ASP.NET Web Application, Part I - Tracing...

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: May 31, 2003 Printer Friendly Version

Introduction

Bugs are a fact of the programmer’s life. How can we deal with them efficiently? In this series of 2 articles I’m going to look at two main areas in order to address this question:

1. Tracing: the process of collecting information about a program’s execution and

2. Debugging: the overlapping topic of finding and fixing errors in your program

We shall look both at the inherent supporting features provided by the .NET framework and ASP.NET and the additional tools provided by VS.NET over the course of the two articles.

Part I shall focus on Tracing, Part II on Debugging, though as I’ve already stated these are overlapping areas as you shall see.

Tracing

Tracing is the ability of an application to generate information about its own execution. The idea is that subsequent analysis of this information may help us understand why a part of the application is not behaving as it should and allow identification of the source of the error.

We shall look at two different ways of implementing tracing in .NET

1. via the System.Web.TraceContext class

2. via the System.Diagnostics.Trace and System.Diagnostics.Debug classes

Tracing can be thought of as a better (more featureful and automated) alternative to the response.writes you used to put in your old ASP3.0 code to help debug pages!

System.Web.TraceContext

The TraceContext class is responsible for gathering the execution details of a web request. The TraceContext object for the current request can be accessed through the Trace property of the Page class. You are thus able to access the functionality exposed by the object’s members, for example writing to the trace log.

By default, tracing is not enabled. It may be enabled at the page level via the Trace attribute of the Page directive. When set to true the page appends the tracing information of the current Web request to its output.

The output of a page with the trace attribute set to ‘true’ will include a host of information in addition to the actual page output, as follows:

Request details: summary details of the page request

Page 2: Debugging an ASP

Trace information: messages either generated by the ASP.NET engine or by you the programmer by making use of the Write or Warn methods in code. Four column output: Category, Message, Time from the first trace item, Duration of this trace item.

Control tree: the entire collection of controls in the ASP.NET page displayed hierarchically.

Collection information: any defined members of the following collections will also be displayed:

← Session state

← Cookies ← Headers ← Form ← Querystring ← Server variables

When tracing is enabled the programmer may add information to the trace information section above via the trace.warn and trace.write. The only difference between these methods is that the warn method displays its text in red, thus allowing the programmer a basic facility to differentiate between the severity of tracing messages. Finally at the page level you may change the order of presentation of trace messages from the default time order (‘SortByTime’) to be based on an alternate via the TraceMode attribute. In fact the only other option is ‘SortByCategory’.

As well as enabling tracing at the page level it can be enabled at the application level using the trace element within the web.config file. This introduces an extra facility: it allows viewing of trace information in a separate page instead of displaying it with the page output. This page is trace.axd which will be located in the application root and is termed ‘trace viewer’ – it lists all the page requests to an application along with summary details and a link to view the full trace log of the request. It also includes a link to clear the current trace information of all page requests.

Note that the page level directive overrides the application level setting. So if you disable tracing for a particularly page you will not see corresponding information via trace.axd.

You can imagine this facility is quite a resource hit and should be used wisely. In particular the facility should be disabled before deployment of the application, when it should be redundant anyway!

Let’s finish of this section with a few examples:

1. Use of trace.write/ trace.warn:

Trace.Write("[category]","[message]")

2. Setting up page level tracing by category:

<% @Page Language="VB" Trace="True" TraceMode="SortByCategory" %>

3. Setting up application level tracing (syntax):

Page 3: Debugging an ASP

<trace enabled="true|false"    localOnly="true|false"    pageOutput="true|false"    requestLimit="integer"    traceMode="SortByTime|sortByCategory" />

Setting localOnly to true makes the trace viewer (trace.axd) available only on the host Web server. The requestLimit is the number of trace requests to store on the server. The default is 10.

System.Diagnostics

Tracing in VB.NET can also be implemented via generating messages with the use of the Debug and Trace classes. The messages generated by default by these classes are viewable in the VS.NET Output Window, though you will see this is configurable shortly.

The two classes are closely related. All their members are conditionally compiled on the basis of whether the DEBUG or TRACE symbols are specified respectively. Visual Basic .NET/ VS.NET provide two basic configurations for a project – Debug (the default) and Release. When you compile a program using the Debug configuration both the TRACE and DEBUG conditional compilation symbols are defined, i.e. when you compile the project any DEBUG or TRACE code in your application will be included and compiled. In the Release configuration only trace information is compiled. These modes are configurable via the property pages of your VS.NET solution. They may also be specified within the program and via command line compilation options.

Some of the members of the debug and trace classes you may choose to use are:

Methods:

Assert: checks for a condition and displays a message if false

Fail: displays an error message

Indent / unindent: increases / decreases the current indent level by one

Write / WriteIf / WriteLine / WriteLineIf: write information to the trace listeners in the listeners collection - conditional or unconditional; with a newline character or without.

Some examples:

Debug.Assert(value<0, "Invalid value","negative value employed in debug mode")

Trace.Writeline(value,"Program trace, value of value")

Properties:

Listeners: the collection of listeners that is monitoring the trace output

See the SDK documentation for full details of the members available.

Which brings us nicely to …

Listeners

Page 4: Debugging an ASP

Listeners are the classes for forwarding, recording or displaying messages generated by the Trace and Debug classes. You can have multiple listeners associated with the Trace and Debug classes by adding multiple listener objects to their Listeners property.

The Listener property is a collection capable of holding objects of any type derived from the TraceListener class. This is an abstract class that belongs to the System.Diagnostics namespace that has three implementations.

1. DefaultTraceListener: an object instantiated from this class is automatically added to the Listeners collection of the Trace and Debug classes. It writes messages to the Output window.

2. TextWriterTraceListener: writes the messages to any class that derives from the stream class. This includes the console or a file.

3. EventLogTraceListener: writes the messages to the windows event log.

Here’s a brief code snippet relating to implementation 2:

'Create a new text writer using the output stream, and add it to'the trace listeners.Dim myFile As Stream = File.Create("TestFile.txt")Dim myTextListener As New TextWriterTraceListener(myFile)Trace.Listeners.Add(myTextListener)

'Write output to the fileTrace.Write("Test output ")

If you require a listener object which acts differently to these you can create your own class, deriving from the TraceListener class to do so.

You may also add TraceListeners from your application web.config file, e.g.

<configuration><system.diagnostics>  <trace>    <listeners>      <add name="myListener" type="System.Diagnostics.TextWriterTraceListener,System" initializeData="c:\myListener.log" />      <remove type="System.Diagnostics.DefaultTraceListener,System"/>    </listeners>  </trace></system.diagnostics></configuration>

Any trace information enabled would then be written to the specified file.

Trace Switches

Trace switches allow you to set the parameters that can control the level of tracing that needs to be performed within a program. These are set via an XML-based configuration file, the web.config file in fact. This might be particularly useful if the application is in production mode and develops a fault you need to resolve. You could instruct a program to generate particular trace messages simply by altering the config file. The changes, as in most situations with .NET, will be picked up automatically.

Page 5: Debugging an ASP

There are two predefined classes for creating trace switches: the BooleanSwitch class and the TraceSwitch class – both derive from the abstract Switch class. As ever, you could also define your own class by deriving from the Switch class.

The BooleanSwitch class differentiates between two modes of tracing: on (non zero) and off (zero, default). In comparison the TraceSwitch class provides 5 different levels of tracing switches defined by the trace level enumeration with the following members:

off 0

error 1

warning 2

info 3

verbose 4

Where each adds an extra level of information to the output.

In your code you could have the following:

dim ts as TraceSwitch([DisplayName],[Description])

If ts.traceVerbose then  debug.writeline(“Nasty big error!”)End If

and you could configure web.config with the following:

<configuration>  <system.web>  .  .  .  </system.web>  <system.diagnostics>    <switches>      <add name=”[DisplayName]” value=”4” />    </switches>  </system.diagnostics></configuration>

Thus, with this configuration verbose error messages will be output. When you don’t want such messages you would simply reduce the trace level to a lower value within web.config. Remember that the location of the output of these messages is down to the rest of your system configuration, as described above.

Conditional Compilation

VB.NET provides a set of pre-processing directives which

← enable you to skip sections of source files for compilation, for example to omit testing code in the released compiled version of your software

← report errors or warnings

Page 6: Debugging an ASP

← mark sections of your code (a la VS.NET windows form designer)

In addition to the pre-processing directives, VB.NET also provides the programmer with the ConditionalAttribute class via which you can mark class members for conditional compilation dependent on symbol values. A symbol value is simply an arbitrary name used for this purpose.

Careful use of these features allow the programmer to keep debugging related code in the source code whilst you are developing an application but to easily exclude it from the finished compiled code. This will remove the associated performance hit from production applications. Further, should the production system encounter an issue you can re-enable the debugging code via a simple switch and recompilation.

Pre-Processing Directives Summary

#If, #Else, #ElseIf, #EndIf: allow conditional skipping of sections of code that will then not be compiled.

#Const: defines a pre-processor constant only viable within a conditional compilation directive.

#ExternalSource, #End ExternalSource: used by the compiler to track line numbers for compiler error messages.

#Region, #End Region: used to mark sections of code. Commonly used by IDEs to show, hide and format code.

ConditionalAttribute Usage example

<Conditional (“DEBUG”)> Public Sub InitializeDebugMode()  lblDebug.Text=”Debug mode”End Sub

In this example, if the symbol is set the Sub will be included in the project compilation. The pre-processing directives can be used similarly.

The DEBUG and TRACE symbols may be modified by

← modifying the VS.NET project’s property pages

← using the #Const directive at the beginning of the code file ← using the /define (/d for short) option with vbc.exe

You are also not restricted to these two symbols for conditional compilation. You can provide your own custom defined symbols via the #Const directive.

Conclusion

I hope that the above has proved a useful overview of the tracing related debugging functionality provided by the .NET Framework and available to the ASP.NET programmer and that you will find these features useful. In the second part of this series of two articles I shall continue on to examine debugging ‘proper’, in particular the use of debugging tools.

Debugging an ASP.NET Web Application, Part II - Debugging...

Page 7: Debugging an ASP

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. Printer Friendly Version

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:

1. 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.

2. 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.

Page 8: Debugging an ASP

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

Page 9: Debugging an ASP

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 TryEnd 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 intFacEnd 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:

Page 10: Debugging an ASP

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:

1. when the exception is thrown

2. 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:

1. Launch the page in Internet Explorer.

2. 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.

3. Open the corresponding source file in VS.NET.

A couple of important points:

1. 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.

2. 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

Page 11: Debugging an ASP

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:

1. Launch the web form that uses the members of the DLL.

2. 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.

3. 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.

Page 12: Debugging an ASP

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 [email protected] or DotNetJohn.

Troubleshooting common permissions and security-related issues in ASP.NETView products that this article applies to.

Article ID

: 910449

Last Review

: May 11, 2007

Revision : 1.1

ASP.NET Support Voice column

Troubleshooting common permissions and security-related issues in Microsoft ASP.NET

To customize this column to your needs, we want to invite you to submit your ideas about topics that interest you and issues that you want to see addressed in future Knowledge Base articles and Support Voice columns. You can submit your ideas and feedback using the Ask For It (http://support.microsoft.com/common/survey.aspx?scid=sw;en;1176&p0=&p1=&p2=&p3=&p4=) form. There's also a link to the form at the bottom of this column.

On This Page

Useful tools Drill down to isolate the problem What is the exact error message? Issue occurs because of missing permissions on a local resource that the

ASP.NET application tries to access Issue occurs because of missing permissions on a remote resource that

the ASP.NET application is trying to access Code Access Security (CAS) related issue Scenario IIS-related errors Resources

Hello, this is Vignesh A.G from the ASP.NET team. Welcome to the ASP.NET Support Voice column! I have been a Developer Support Engineer for over two years now at Microsoft, and I have spent my time focusing on ASP.NET and Microsoft Internet Information Services (IIS).

The focus of this column will not be to explain ASP.NET security, but to outline a few troubleshooting techniques and tips that will help you isolate and resolve some of the common permissions and security scenarios that we see here at PSS. Permissions and security-related issues in ASP.NET are very well documented. In fact, there will

Page 13: Debugging an ASP

be a good number of people who might have run into the same issue prior to you. So, the intent is for this column to be a good place to find relevant and exhaustive information on ASP.NET security. There is no better feeling than fixing the issue yourself.

Back to the top

Useful toolsBefore you attempt to fix anything that is broken, you need to familiarize yourself

with a few tools which will help you narrow down the issue. In our case, we would be interested in tools like FileMon, RegMon, and Security Auditing. For more information about FileMon, visit the following Microsoft Web site: http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx (http://www.microsoft.com/technet/sysinternals/FileAndDisk/Filemon.mspx)For more information about RegMon, visit the following Microsoft Web site: http://www.microsoft.com/technet/sysinternals/SystemInformation/Regmon.mspx (http://www.microsoft.com/technet/sysinternals/SystemInformation/Regmon.mspx)

Back to the top

Drill down to isolate the problem

Has the application ever worked? If yes, then what changed that could have made the application break? It's possible that software updates or security updates were applied on the server. A code rollout also could have caused the issue.

• Do simple .html and .asp pages serve from IIS?• Was the application migrated to a different version of IIS?

• Do other ASP.NET applications on the server fail with the same error? Is this the only application that fails?

• Does the issue occur for all users or for only specific users?

• Is the issue reproducible while browsing locally on the Web server, or is it reproducible for only a few clients?

• If you are using impersonation, then does the impersonated user have the necessary access to the resource?

The above questions are useful in order to diagnose a problem. If you are posting your issue on any of the ASP.NET forums, and if you already have the answers to most of these questions, then it's likely that you will get a quick pointer or solution to your problem. The key is to post the whole ASP.NET stack trace error, if applicable, instead of saying "I am getting an Access Denied error while trying to run my ASP.NET application. Can anyone help?" It's much easier for someone to look at the stack trace and give you pointers when they can see a complete error message. So you need to ask yourself...

Back to the top

What is the exact error message?The first question we ask customers is, "What is the exact error message?" If you

have a clear description of the error message thrown by the Microsoft .NET Framework, you can skip this section. If your application masks the actual error message and gives you a friendly error message instead, such as, "An unexpected error has occurred. Please contact the website administrator for details," it's not of

Page 14: Debugging an ASP

much use to anyone. Here are a few steps which will help you get the actual error message.

• Locate and open the Web.config file in the application directory and change customErrors to mode="Off". Save the file, and reproduce the problem.

It still might not be possible to see the actual error message after following the above step because of custom event/error handling done by the application developer. You can try to locate the Application_Error event in the Global.asax file and comment out any code that uses the Server.Transfer("Errors.aspx") function to go to a custom error page.

/Global.asax

void Application_Error(object sender, EventArgs e)

{

// Code that runs when an unhandled error occurs

//Server.Transfer("Errors.aspx");

}

Once you get the actual error message, read it to determine if the error is caused by missing permissions on a local resource or on a remote resource that your ASP.NET application is trying to access.

Tip You can contact your developer to find out how to see the actual error message. It's possible that your developer may be logging it to a file or getting e-mail notifications. Always remember to make a backup of any file that you are going to change. With a backup available, you can always roll back any changes.

Back to the top

Issue occurs because of missing permissions on a local resource that the ASP.NET application tries to access

If you are unable to get a clear description of the problem because of a custom error message, run FileMon and reproduce the problem. Stop and save the capture as FileMon.xls and open the file in Microsoft Excel. On the Data menu, click Filter, and then click AutoFilter to use the filtering capabilities of Excel. Now select the drop-down list in column F and look for "ACCESS DENIED" errors.

A sample FileMon output is shown below.

10381 1:01:11 PM w3wp.exe:2320 OPEN

C:\winnt\microsoft.net\framework\v1.1.4322\Temporary ASP.NET

Files\sessiontest\8832e585\275ec327\global.asax.xml ACCESS DENIED NT

AUTHORITY\NETWORK SERVICE

Page 15: Debugging an ASP

As you can see from the filtered results, we have narrowed down the cause of the problem. FileMon shows that the NT AUTHORITY\NETWORK SERVICE account is missing NTFS permissions on the C:\Winnt\Microsoft.net\Framework\v1.1.4322\Temporary ASP.NET Files folder. This should be straight forward to fix. For more information about using FileMon to troubleshoot ASP.NET, click the following article number to view the article in the Microsoft Knowledge Base: 890960 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=890960/) Troubleshooting ASP.NET using FileMon Tip A good step would be to change the ASP.NET process account to an Admin account to see if it fixes the problem. In IIS 5.x you would change the userName to "SYSTEM" in the process model section of the machine.config file and in IIS 6.0 you would change the IIS AppPool identity to "Local System" to see if the application works.

Note This should not be used as a solution, but only as a troubleshooting step.

Most people would tend to reinstall the Microsoft .NET Framework or even go to the extent of reinstalling the operating system. This is not a recommended troubleshooting step and does not guarantee that the issue will not reoccur. I will provide one such example. Intermittent issues are often hard to isolate and troubleshoot. In this scenario the customer's application would work fine for a few hours, and then all of a sudden it would fail with the error below. The customer had already tried reinstalling the .NET Framework as well as the operating system. This seemed to fix the problem for a few days, but then it reappeared.

Running FileMon did not show any ACCESS DENIED errors. All the necessary permissions for the ASPNET account were in place. The only way to recover from the problem is to reboot the box. Even an IIS reset would not help. You are thinking "Ah, Microsoft Software always needs a reboot to recover?" Well, you are wrong!

The key here is to look closely at the error message. The error clearly says "cannot open a file for writing," and not the usual ACCESS DENIED error, so I am thinking that it's some other process that is holding a lock on a file or folder and not allowing ASP.NET to write to it. It makes sense that a reboot was killing the other process and the ASP.NET application starts working again until the rogue process locks the file again. The logical thing to do would be to turn off all antivirus programs, third-party spyware, or any other file monitoring software that runs on the server. I do not want to point out any specific third-party software. But, in general, antivirus software is known to cause a lot of grief for IIS and ASP.NET applications. Another known issue caused by antivirus software is session loss due to AppDomain recycles when the Bin folder or the .config files are touched.

Tip The easiest way to turn off third-party services is to: 1. Click Start, click Run, and then type msconfig.

Page 16: Debugging an ASP

2. Select Services and check Hide All Microsoft Services.3. Click Disable All to stop the third-party services.

4. Click Start, click Run, and then type iisreset to reload the CLR into the worker process.

Monitor your application to see if the issue reoccurs. If you run multiple antivirus programs, use the trial-and-error method to determine which particular program is causing the issue.

Note If the same error is reproducible 100 percent of the time, your antivirus software may not be the cause. There can be other causes for this error. Try creating a simple ASP.NET test application to isolate whether the same error occurs for a Test.aspx page. If it does, then verify that the required Access Control Lists (ACLs) are all in place for ASP.NET.

See ASP.NET Required Access Control Lists (ACLs): http://msdn2.microsoft.com/en-us/library/kwzs111e.aspx (http://msdn2.microsoft.com/en-us/library/kwzs111e.aspx)

Tip The %SystemRoot%\Assembly folder is the global assembly cache. You cannot directly use Windows Explorer to edit ACLs for this folder. Instead, use a command prompt and run the following command: cacls %windir%\assembly /e /t /p domain\useraccount:rAlternatively, prior to using Windows Explorer, unregister Shfusion.dll with the following command to give permissions via the GUI: C:\WINDOWS\Microsoft.NET\Framework\VersionNumber>regsvr32–u shfusion.dllAfter setting permissions with Windows Explorer, re-register Shfusion.dll with the following command: C:\WINDOWS\Microsoft.NET\Framework\VersionNumber>regsvr32 shfusion.dll

Back to the top

Issue occurs because of missing permissions on a remote resource that the ASP.NET application is trying to access

When your ASP.NET application is accessing a remote resource like Microsoft SQL Server or a Universal Naming Convention (UNC) share, there are many things that can go wrong. Also, many things may be incorrectly set up on the remote resource. You'll need to troubleshoot those issues in order to get the resource working. For more information, click the following article number to view the article in the Microsoft Knowledge Base: 891031 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=891031/) Common security issues when you access remote resources from ASP.NET applications Your first step would be to see if you can connect to the remote server through Windows Explorer.

1.

On the remote server, create a folder called Test. On the Sharing and Security tabs of the Test folder, add your domain/account, and also the process account that is used by your ASP.NET application, and give them both Full Control.

Note Please see891031 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=891031/) for techniques or workarounds to access remote resources from ASP.NET.

2. On the IIS server, log in with your domain/account, click Start, click Run, and then type the UNC share path of the remote server: \\RemoteServerName\Test If you are unable to get to this folder, then contact your Network Administrator to

Page 17: Debugging an ASP

fix this issue. Only then can your ASP.NET application access the share. 3. Create a file called CreateUNCFile.aspx with the code below and save the file in

your application directory.

<%@ Page Language="vb" %>

<%@ Import Namespace="System.IO" %>

<html>

<head>

<title>Writing to a Text File</title>

<script runat="server">

Sub WriteToFile(ByVal sender As System.Object, ByVal e As System.EventArgs)

Dim fp As StreamWriter

fp = File.CreateText("\\<RemoteServerName>\Test\" & "test.txt")

fp.WriteLine(txtMyFile.Text)

lblStatus.Text = "The File Successfully created! Your ASP.NET process is able to access this remote share"

fp.Close()

End Sub

</script>

</head>

<body style="font: 10pt verdana">

<h3 align="center">Creating a Text File in ASP.NET</h3>

<form id="Form1" method="post" runat="server">

Type your text:

<asp:TextBox ID="txtMyFile" TextMode="MultiLine" Rows="10" Columns="60" Runat="server" /><br>

<asp:button ID="btnSubmit" Text="Create File" OnClick="WriteToFile" Runat="server" />

<asp:Label ID="lblStatus" Font-Bold="True"

Page 18: Debugging an ASP

ForeColor="#ff0000" Runat="server" />

</form>

</body>

</html>

4.

Make sure that you modify <RemoteServerName> in the following line of code

fp = File.CreateText("\\<RemoteServerName>\Test\" &"test.txt")

so that it reflects the name of your remote server.

5.Open Windows Internet Explorer and browse to http://IISServerName/AppName/CreateUNCFile.aspx from a client computer other than the IIS server.

6. If the Test.txt file creates successfully, then your ASP.NET application can authenticate to the remote resource.

7.

If file creation fails from an Internet Explorer client browser but works if you browse to the same page from the IIS server itself, then it's likely that you are running into a "Double Hop" scenario. If you are using custom built Web Parts to access remote resources that require user authentication and authorization, you will probably run into the "Double Hop" problem. In order to access your remote resource, you may need to supply the end user's credentials to the resource so that the output from the resource is limited to the data that the end user has permission to access.

The above steps assume that you have NTLM Authentication turned on in IIS. Basic Authentication does not use Kerberos. For more information, click the following article number to view the article in the Microsoft Knowledge Base: 907272 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=907272/) Kerberos authentication and troubleshooting delegation issues 326985 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=326985/) How to troubleshoot Kerberos-related issues in IIS For more information on IIS authentication methods, see the following Microsoft Developer Network (MSDN) Web site: http://msdn2.microsoft.com/en-us/library/aa292114(VS.71).aspx (http://msdn2.microsoft.com/en-us/library/aa292114(VS.71).aspx)

Tip If you can connect to the remote UNC share but you can not connect to the remote server that is running SQL Server from the ASP.NET application, then you might have to check or set the Service Principal Names (SPNs) for SQL Server. Try enabling only Basic Authentication for your application in IIS and see if you are able to connect to the remote server that is running SQL Server. For more information, click the following article number to view the article in the Microsoft Knowledge Base: 319723 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=319723/) How to use Kerberos authentication in SQL Server 316989 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=316989/) Error message when you create a trusted data connection from ASP.NET to SQL Server: "Login failed for user: 'AccountName'" Tip It's never recommended to use mapped drives to connect to a remote resource because drive mappings are an extension of the net use command and are created on a per-user basis. The preferred method of accessing content for the Web server

Page 19: Debugging an ASP

that exists on a remote computer is to use shares that follow the UNC. For more information, click the following article number to view the article in the Microsoft Knowledge Base: 257174 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=257174/) Using mapped drives with IIS

Back to the top

Code Access Security (CAS) related issueError messages in ASP.NET are detailed and, more often than not, tell you exactly

what the problem is. In some cases, FileMon or RegMon may not capture anything useful. Let's take a look at one such scenario. Scenario

While trying to browse an ASP.NET application, it fails with a generic error such as the following infamous error:

The event log shows: Event Type: ErrorEvent Source: ASP.NET 1.1.4322.0Event Category: NoneEvent ID: 1088Date: 10/11/2006Time: 10:54:04 PMUser: N/AComputer: ComputerNameDescription:Failed to execute request because the App-Domain could not be created. Error: 0x8013150aWhen an ASP.NET application domain is created, ASP.NET reads the value specified for the level attribute of the trust configuration element, creates an instance of the AspNetHostingPermission class with the specified Level attribute, and then adds the class to the permission set for the application domain. You will see the above error if the trust levels are incorrectly configured or modified. For more information, see "ASP.NET Trust Levels and Policy Files" at the following MSDN Web site: http://msdn2.microsoft.com/en-us/library/wyts434y.aspx (http://msdn2.microsoft.com/en-us/library/wyts434y.aspx)To resolve this issue, you can try this Tip in the "Issue occurs because of missing permissions on a local resource that the ASP.NET application tries to access" section, but do not get disheartened if the application does not work with an Administrator or SYSTEM account. You need to check to see if the issue can be caused by Code Access Security. This can easily be done by turning off Code Access Security using the Caspol.exe utility.

Page 20: Debugging an ASP

C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>caspol -s offMicrosoft (R) .NET Framework CasPol 1.1.4322.573 Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Success

C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>Once you have runcaspol –s off, reset IIS and try to browse the application. If this step works, you then need to check the permission set for the code groups. You can access the code groups in the Microsoft .NET Framework VersionNumber Configuration tool that is found in Administrative Tools.

In this scenario, the Permission Set for the My_Computer_Zone code group was set to Nothing. Changing it to Full Trust resolved the issue

Note To access the My_Computer_Zone code group, follow these steps: 1. In Control Panel, double-click Administrative tools.

2. Double-click Microsoft .NET Framework VersionNumber Configuration.

3. Double-click Runtime Security Policy.4. Double-click Machine.5. Double-click Code Groups.6. Double-click All_Code.7. Double-click My_Computer_Zone.Tip Remember to run caspol –s on to turn on CAS once you have fixed the issue.

For more information, see ASP.NET Code Access Security: http://msdn2.microsoft.com/en-us/library/87x8e4d1.aspx (http://msdn2.microsoft.com/en-us/library/87x8e4d1.aspx)

There are numerous other causes for the "Server Application Unavailable" error message. The event log is your best bet to get more details on the cause of your issue.

Back to the top

IIS-related errorsThe IIS logs are very useful in cases of IIS authentication-related errors. A common

scenario is when the user would typically see the following:

What you need to look for is the status and sub status codes for this particular error.

Page 21: Debugging an ASP

2006-10-12 22:47:28 W3SVC1 65.52.18.230 GET /MyAPP/login.aspx - 80 MyDomain\UserID_91 65.52.22.58 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+InfoPath.1) 401 3 5We see a 401 with the sub-status 3, which indicates "Unauthorized due to ACL on resource."

This indicates missing NTFS permissions on a file or folder. This error may occur even if the permissions are correct for the file that you are trying to access, but the default permissions and user rights may be missing on other SYSTEM and IIS folders. For example, you may see this error if the IUSR_ComputerName account does not have access to the C:\Winnt\System32\Inetsrv directory. For more information about IIS status codes, click the following article number to view the article in the Microsoft Knowledge Base: 318380 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=318380/) IIS status codes 812614 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=812614/) Default permissions and user rights for IIS 6.0 271071 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=271071/) How to set required NTFS permissions and user rights for an IIS 5.0 Web server Tip Click Start, click Run, and then type logfiles to open the folder that contains the IIS logs. Alternatively, on the properties page for your Website in IIS, click the WebSiteName tab, and under Active log format, click Properties to see the Log file directory and name.

The other thing of interest here is the status code 5. You can use the net helpmsg command to get more info on this status code: C:\Documents and Settings\User>net helpmsg 5Access is denied.Let's try another common status code, code 50: C:\Documents and Settings\User>net helpmsg 50 The request is not supported.Tip Whenever you get another generic infamous "500 Internal Server Error" message, then it's a good idea to disable friendly HTTP error messages, so that you receive a detailed description of the error. Don't forget to look in the event viewer as it may also contain more information. For more information about how to disable friendly HTTP error messages, click the following article number to view the article in the Microsoft Knowledge Base: 294807 (http://www.kbAlertz.com/Feedback.aspx?kbNumber=294807/) Turn off the Internet Explorer 5.x and 6.x "show friendly HTTP error messages" feature on the server side The idea is to use all the logged information available to get maximum details on the problem at hand.