ASP .NET applications offer a rather different debugging experience from desktop applications. When debugging ASP .NET, you have to deal with potential complications caused by elements such as firewalls, security, folder permissions, account permissions, and IIS itself. When everything works smoothly, you can step seamlessly from a Web page to a code-behind assembly to a class library and then back again. However, when debugging fails for some reason, you usually need some understanding of the underlying technologies to identify exactly where the debugging process is failing. This section discusses how to set up ASP .NET debugging and how to overcome some of the issues that you're likely to encounter.
By default, an ASP .NET application runs under the ASPNET Windows account. This is a security feature because the ASPNET account is given limited permissions by default and so can do only a limited amount of damage if hijacked. The important issue from a debugging point of view is that a developer can only debug a process running under another Windows account (such as ASPNET) if that developer belongs to the Administrators group on the machine where the process is running. In other words, if you want to debug an ASP .NET application, it's not sufficient for you to be in just the Users and Debugger Users groups, as discussed at the start of Chapter 4.
To add and remove user accounts to and from groups when using Windows 2000, go to the Control Panel and choose Administrative Tools ’ Computer Management ’ System Tools ’ Local Users and Groups ’ Groups. Windows XP and Windows Server 2003 also allow maintenance of users and groups from the Control Panel.
If you really don't want, or aren't allowed, to add your developer's user account to the Administrators group, there are a couple of possible workarounds. One (rather insecure ) approach is to tell the ASP .NET worker process to run under your developer account by adding some entries to the .NET machine configuration file, machine.config. To do this, go to the <processModel> section of machine.config and modify the username and password settings ( marked in bold in the following code) to match your Windows domain, account name , and password:
<processModel enable="true" timeout="Infinite" idleTimeout="Infinite" shutdownTimeout="0:00:05" requestLimit="Infinite" requestQueueLimit="5000" restartQueueLimit="10" memoryLimit="60" webGarden="false" cpuMask="0xffffffff" userName="YourDomain\YourAccountName" password="YourPassword" logLevel="Errors" clientConnectedCheck="0:00:05" comAuthenticationLevel="Connect" comImpersonationLevel="Impersonate" responseDeadlockInterval="00:03:00" maxWorkerThreads="20" maxIoThreads="20"/>
After you make this change and save the machine.config file, you must reset IIS by using the iisreset command from the Visual Studio .NET command prompt. You should also give your user account full permissions to the Temporary ASP .NET Files folder, which sits under C:\WINNT\Microsoft .NET\Framework\version\. To do this, right-click the folder in Windows Explorer and select the Properties item from the context menu. In the resulting dialog window, choose the Security tab and click the Advanced button, as shown in Figure 9-3.
In the Access Control Settings for Temporary ASP .NET Files dialog window, click the Add button and add your user account. Finally, in the Permission Entry for Temporary ASP .NET Files dialog window, give your user account full permissions. After doing all of this, you should be able to debug ASP .NET applications without being an administrator, although you still need to be a member of the Debugger Users group.
It's important to realize that there are security issues involved with this approach. For example, your own user account may have permissions that you wouldn't normally want to give to ASP .NET applications, but now any ASP .NET executable that runs will inherit your user account's permissions. Also, this approach means that your password is stored in clear text in machine.config. An alternative method for enabling ASP .NET debugging that doesn't have the same security issues is to create a new "weak" user account (for instance, ASPUSER) with the same permissions as the standard ASPNET account, and then configure the <processModel> section as previously to use ASPUSER for running the ASP .NET worker process. Then you can add ASPUSER to the Users and Debugger Users groups and use it to do your ASP .NET debugging. This means that the ASP .NET worker process is now running under the same account that you're using to do the debugging, so there's no requirement to add ASPUSER to the Administrators group.
There are some additional requirements if you're debugging an ASP .NET application that's running on a remote Web server. First, you need to add the ASPNET account to the Debugger Users group on the remote machine. This is required even if the user account you're using for debugging is in the Administrators group on the remote machine. Second, the local workstation must be running Windows NT 4.0, Windows 2000, Windows XP (any edition except Home), or Windows 2003. The remote machine must be running Windows 2000, Windows XP (any edition except Home), or Windows 2003. Finally, both machines should be in the same domain.
If you're using a workgroup setup, you should use the same Windows user account and password on both machines. If you don't do this, DCOM (the transport protocol used by default for remote debugging) will fail to authenticate your user account. If you're using a workgroup setup based on Windows XP Professional for remote debugging, there's an additional consideration. The default security setting for "sharing and security model for local accounts" doesn't allow remote debugging. To fix this, run the "Local Security Settings" utility in Administrator tools and select "Security settings\Local policies\Security options". Change the "Network access: Sharing and Security model for local accounts" from "Guest only “ local users authenticate as Guest" to "Classic “ local users authenticate as themselves ". Then reboot the machine for the new setting to take effect. You need to do this on both the local workstation and the remote machine.
This does pose a security risk, because now any connection from one machine to the other could be authenticated as your local user account rather than as a guest, so I advise changing this setting back to its default value after you've completed the remote debugging session.
For more information on remote debugging, please see Chapter 15.
If you're using Internet Explorer to run your ASP .NET applications, there are a couple of options that you can deselect to make your debugging life easier. If you select Tools ’ Internet Options and then go to the Advanced tab's Browsing section, you'll see the two options "Disable script debugging" and "Show friendly HTTP error messages," as shown in Figure 9-4.
During ASP .NET debugging sessions, you should normally deselect both of these options. The first option setting is self-explanatory, but the second option setting deserves an explanation. The difference between selecting and deselecting this option is the effect that an ASP .NET application exception has on the browser. If you opt for friendly HTTP error handling, the result of an exception is the standard noninformative browser message "Page cannot be displayed". If you turn off this option, the browser displays the actual exception message. I presume that "friendly" in this context means friendly to the application's end users.
Every ASP .NET application contains an XML configuration file named Web.config. This configuration file includes several settings that control application behavior.
In Web.config, you need to ensure that the <compilation debug=/> option is set to true in order to perform debugging of an ASP .NET application.
<system.web> <compilation defaultLanguage="vb" debug ="true" /> </system.web>
Changing this setting to true tells Visual Studio to generate debug symbols for any dynamically generated page. It also allows the Visual Studio debugger to attach to the application. The major reason to be wary about this setting is that enabling debugging will make your ASP .NET application run much slower than normal, so it's advisable to make sure that this option is set to false before you release your application into a production environment.
Be aware that when <compilation debug=/> has the value of true , ASP .NET ignores the <httpRuntime executionTimeOut =/> setting and also ignores any calls to Server.ScriptTimeout . This avoids any time-out problems when you're stepping through code or paused at a breakpoint, but it has an undesirable side effect. If no response to an HTTP request has been received from your ASP .NET application for a period longer than that specified in the <processModel responseDeadlockInterval =/> configuration setting, the ASP .NET worker process is recycled and your debugging will be interrupted . To avoid this timeout issue when you're debugging, you should change the <processModel responseDeadlockInterval =/> configuration setting to the value of Infinite for the duration of a debugging session.
ASP .NET automatically detects any changes to Web.config, so you don't need to reboot or restart the server for changes to take effect. But be aware that these attribute names are case sensitive, so using Debug rather than debug won't work!
Another important Web.config setting is the <customErrors mode=/> setting. This setting controls how errors that are unhandled at the page level are displayed to the users of your application and looks like this:
<system.web> <customErrors mode ="RemoteOnly" /> </system.web>
There are three possible settings for this option:
If mode=Off , all clients , whether remote or local, receive a detailed ASP .NET error page that "explains" the unhandled error.
If mode=On , local clients see any custom error page that you've defined, whereas remote clients receive the detailed ASP .NET error page.
If mode=RemoteOnly , local clients see the detailed ASP .NET error page, whereas remote clients see any custom error page that you've defined.
Normally you're likely to be developing your ASP .NET application locally. In this case, the setting you should use depends on whether you're testing your error handling. If you want to see the real exceptions, you should set mode=RemoteOnly . If you want to test your custom error pages, you should set mode=On .
If you're developing your ASP .NET application on a remote server, you need to reverse these settings. So to see the real exceptions, you should set mode=On , and if you want to test your error handling, you should set mode=RemoteOnly .
For a production server, you should always use the mode=RemoteOnly setting. This ensures that hackers don't see any detailed information that might be of use to them in the event of an unhandled error. Instead, the only information displayed will be one of the custom error pages that you've defined. Another reason for not displaying the detailed ASP .NET error page is that it's rarely of any use to end users, and it's quite likely to overwhelm the end users with useless information. Once again, defining and using a custom error page lets you communicate better with your end users by suggesting a workaround or allowing them to try something different.
ASP .NET automatically detects any changes to Web.config, so you don't need to reboot or restart the server for changes to take effect. But be aware that these attribute names are case sensitive, so using on rather than On won't work!
You should also check that your ASP .NET application is configured for debugging within Visual Studio. Right-click your ASP .NET project in Solution Explorer and go to the Properties ’ Configuration Properties ’ Debugging property page and make sure that the "ASP .NET debugging" option is selected, as shown in Figure 9-5.
On the Properties ’ Configuration Properties ’ Build property page of your project, ensure that the "Generate debugging information" option is selected. This ensures that debug symbols will be generated for the project. On the same property page, you can specify how your ASP .NET application should be started for a debug or test session. This is controlled by the Start Action setting, which has four options:
Start project : This option allows you to start your ASP .NET project directly at the specified Web page. The default Web browser is launched and displays this Web page. This is usually the best option to use when you're testing and debugging a straightforward project.
Start external program : Select this option if you want to test a component of your ASP .NET application using a program external to your Visual Studio solution as its client. When you choose this option, the Visual Studio debugger attaches to the ASP .NET application, but not to the external program.
Start URL : This has the same effect as the "Start external program" option just discussed, but it uses an external Web page as the client rather than an external program.
Wait for an external process to connect : This option is really for testing a Web service rather than a standard ASP .NET application. It's similar to the "Start external program" option discussed previously, but the Visual Studio debugger attaches itself to both your ASP .NET component and the process that uses the component.
During everyday debugging, the "Start project" setting is the most likely way that you'll test and debug your application.