Here's the scenario:
- A standard user control with a code-behind file is hosted in an insignificant ASPX page;
- The user control code-behind is doing some work to render the control and also has a handler method subscribing to a button click event;
- The relevant assemblies are built in debug mode and are deployed to a separate development server along with the associated markup files;
- The assemblies on the server are the same version as those on the development workstation;
- The application is configured as it should be in IIS and the debug attribute on the web.config's compilation element is set true;
- The VS 2005 remote debugger is installed and running on the dev server;
- The VS 2005 "client" is attached to the remote server's ASP.NET worker process (w3wp.exe in this case);
- Two breakpoints are set on the user control code: one on Page_Load and one on the button click handler;
- Browsing to the host page doesn't cause the debugger to break (except intermittently, sometimes following an iisreset)...
Here's the problem:
The user control in question had an OutputCache directive set to cache the control for sixty minutes. Removing this little devil resulted in a slap of the forehead and allowed the debugger to break as expected.
The OutputCache directive prevents the control being added to the control tree of the hosting page at runtime; ASP.NET loads an existing version from the cache instead of executing the control code.
...kind of a silly problem since the debugger gives you no inidication the control is loading from the cache but it's all too easy to forget about this sort of thing!!! The golden rule I usually try to apply is to hold off on performance tuning until the very end of the development/testing process and this should generally include large-scale caching. Obviously this doesn't apply in a maintenance situation.
[Update: a few additional tips...
- Double-check the deploy location of your assembly; if it's in the GAC you can deploy to the bin directory until the cows come home but ASP.NET will continually load the assembly from the GAC. Either remove the GAC'd assembly or deploy to the GAC (you can also deploy PDB files to the GAC but you need to drop them under gac_msil using the command line).
- Once you've attached the debugger, bring up the Modules window (Debug -> Windows -> Modules); locate your assembly and verify whether symbols have been loaded and the location where the assembly was loaded.]