This section covers IIS information about which you should be aware when you're debugging ASP .NET applications that run under version 5. x and version 6.0 of IIS. This includes how IIS detects and deals with problems in ASP .NET applications and any debugging restrictions imposed by the different IIS 5. x and IIS 6.0 architectures.
When you run your ASP .NET application on an IIS 5. x Web server, the aspnet_wp.exe executable implements the HTTP runtime, which controls most of the elements that make up your application. This executable runs an ASP .NET worker process controlled by IIS. On a single-processor system, IIS 5. x runs all Web applications, including Web services, within this single process.
When you run your ASP .NET application on an IIS 6.0 Web server, the w3wp.exe executable implements the HTTP runtime. Just as with IIS 5. x , this executable runs an ASP .NET worker process controlled by IIS, but you can configure IIS 6.0 to run multiple ASP .NET worker processes.
IIS 5. x currently has the limitation that only one debugger can be attached to an ASP .NET worker process at any one time. Even though internally the worker process isolates your Web application from other applications by using application domains, it's not possible for more than one developer at a time to debug ASP .NET applications (or other Web applications) on the same machine. The Microsoft development model seems to encourage each developer to test and debug her Web application on her local machine, before moving the application to a proper Web server in a production environment. If you want multiple developers to debug their Web applications on a single machine using IIS 5. x , you're unfortunately out of luck.
If your ASP .NET application is running on a multiprocessor machine, you'll see one ASP .NET worker process for each processor on the machine, an architecture sometimes referred to as a Web garden . You might think that having multiple ASP .NET worker processes means that multiple developers can do ASP .NET debugging simultaneously . Unfortunately, this doesn't work because there are no guarantees about which worker process will handle any particular HTTP request. Even if you manage to attach to the correct process for your application's first HTTP request, the remaining requests will potentially be processed by one of the ASP .NET worker processes to which you're not attached.
A major difference between IIS 5. x and IIS 6.0 is that with the latter you can enable worker process isolation mode . This has the effect of grouping all configured Web applications into application pools, with each application pool run by a separate w3wp.exe process. You can further specify that each AppDomain (logical process) is executed in its own application pool. Because each application pool is in turn running its own w3wp.exe process, multiple developers can debug on a single IIS 6.0 Web server because each developer can attach his debugger to the w3wp.exe process running his own application. This removes the multideveloper debugging issue discussed in the previous section.
Another issue with debugging ASP .NET applications running on IIS 5. x is the way in which the built-in health monitoring works. IIS 5. x health monitoring occurs when the <processModel enable =/> setting in machine.config is set to true . All ASP .NET worker processes are then monitored for specific health criteria. For instance, when the size of any one process reaches a certain percentage of the total memory available to the system (by default, 60% of the system's physical memory), the worker process is then recycled. This recycling involves suspending all requests to that process, routing requests to a new worker process, and then stopping and restarting the original process.
Although this health monitoring is very useful from a production support point of view, the problem is that the worker process can be recycled even though you've already attached a debugger to the process to investigate the problem. To avoid this annoying behavior, you can use the Windows registry to control whether process recycling happens when a debugger is attached to a process. Under HKLM\Software\Microsoft\ASP .NET, you should create two registry settings, namely UnderDebugger and DebugOnHighMem . These registry settings should both be created as DWORD values. Setting the UnderDebugger registry option to the hex value of 1 disables the process recycling mechanism. Setting the DebugOnHighMem registry option to the hex value of 1 is the equivalent of setting a breakpoint that triggers (by invoking the Win32 DebugBreak API) when the memory monitoring mechanism detects that the memory limit has been exceeded.
Both of these registry settings are officially undocumented, so they may change or even disappear altogether when a new version of ASP .NET arrives. Even for the current version of ASP .NET, I recommend that you create and use these registry settings only during a specific debugging session.
An ASP .NET worker process can, of course, be recycled for reasons other than consuming too much memory. For instance, you may see an ASP .NET process deadlock when two threads are each trying to gain access to a resource locked by the other thread. In this case, ASP .NET health monitoring will detect the deadlock and automatically recycle the process as soon as the time mentioned in the <processModel responseDeadlockInterval =/> machine.config setting has elapsed. If you want to attach to the process and debug a deadlock before the process has been recycled, you need either to install version 1.1 of the .NET Framework or install the hot fix discussed in Microsoft Knowledge Base article Q325947. Then you can add the registry DWORD settings UnderDebugger (as just discussed) and DebugDeadlock , both under HKLM\Software\Microsoft\ ASP .NET. Setting the latter key to the hex value of 1 triggers a break into the ASP .NET worker process (aspnet_wp.exe) when a deadlock is detected , whereas using a hex value of 2 breaks into both aspnet_wp.exe and Inetinfo.exe. This allows you to debug ASP .NET process deadlock problems without interference from process recycling. Although these registry settings are documented and shouldn't disappear arbitrarily, you should probably remove them when you aren't debugging ASP .NET applications.
IIS 6.0 uses the Web Administration Service (WAS) to recycle any ASP .NET worker process that fails to meet specified health criteria or fails to respond to pings . Just like with IIS 5. x , this recycling can complicate debugging by removing a process before you get a change to attach a debugger. However, IIS 6.0 improves upon IIS 5. x 's undocumented facility for controlling this recycling.
You can configure WAS to "orphan" a process that has failed health monitoring. The worker process to be orphaned is removed from its application pool but kept running so that you can initiate a debugging investigation. Then a new worker process is started to handle the application's requests. To arrange for defective ASP .NET processes to be orphaned in this way, run the following command from the \Inetpub\Adminscripts folder, replacing <apppoolname> with the name of the relevant application pool:
cscript adsutil.vbs set w3svc/apppools/<apppoolname>/orphanworkerprocess 1
To apply this setting for all application pools, you can instead issue the following command:
cscript adsutil.vbs set w3svc/apppools/orphanworkerprocess 1
These commands allow you to debug an ASP .NET application running on IIS 6.0 even after it's failed a health monitor check and therefore been removed from service.
URLScan is an ISAPI filter supplied by Microsoft that works in conjunction with the IIS Lockdown tool to help IIS administrators secure their Web servers by restricting the HTTP requests that the servers will process. URLScan screens all incoming requests to the server and filters them based on rules defined by the IIS administrator. If the URLScan filter has been installed on your ASP .NET Web server, you'll need to configure it to allow debugging.
To do this, find the file URLScan.ini and add the keyword DEBUG (this is case sensitive) into the [AllowVerbs] section while making sure that the same keyword isn't in the [DenyVerbs] section. You should also ensure that the [AllowVerbs] section is enabled by adding the setting UseAllowVerbs = 1 .
In some circumstances, especially on a production Web server, you might find that IIS itself doesn't permit the DEBUG verb for ASP .NET applications. To check this, run the IIS Manager utility and find your application's folder under \Inetpub\wwroot. Right-click the folder and select the Properties menu item. In the resulting Properties dialog window, go to the Directory tab and click the Configuration button. In the Application Configuration dialog window, go to the Mappings tab, as shown in Figure 9-1.
Edit the .aspx extension and make sure that DEBUG is in the list of allowed verbs.
You should make sure that your ASP .NET application's IIS authentication is set up in a way that permits debugging. To do this, run the IIS Manager utility and find your application's folder under \Inetpub\wwroot. Right-click the folder and select the Properties menu item. In the resulting Properties dialog window, go to the Directory Security tab and click the Edit button in the "Anonymous access and authentication control" section. In the Authentication Methods dialog window, ensure that the "Integrated Windows authentication" option is selected, as shown in Figure 9-2.
The most common reason for seeing the infamous "Unable to start debugging on the Web server" message when you start an ASP .NET application is that this option hasn't been selected.
Because the ASP .NET worker process is multithreaded and processes requests asynchronously, you need to be sure that all of your ASP .NET components are either thread-safe or never called on multiple threads simultaneously. Although ASP .NET ensures that Web Forms themselves are never re-entrant , you must add your own threading synchronization anywhere that you define a Shared method or property and anywhere that you use .NET Framework classes that are not thread-safe. For example, none of the .NET collection classes is thread-safe, and neither is the intrinsic Application object. Finally, be careful if you use any single-threaded apartment COM components (such as those written in VB.Classic) in your ASP .NET applications.
To find out more about the potential problems when designing and writing multithreaded applications, please see Chapter 14.
When you attach a debugger to the ASP .NET worker process, all threads in that process are frozen, which means that no HTTP requests will be serviced. This has obvious implications if you're trying to debug a production Web server, so it's normally best to withdraw the server from production before debugging it.