Don’t run production ASP.NET Applications with debug=”true” enabled

One of the things you want to avoid when deploying an ASP.NET application into production is to accidentally (or deliberately) leave the <compilation debug=”true”/> switch on within the application’s web.config file.

 

Doing so causes a number of non-optimal things to happen including:

 

1) The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)

2) Code can execute slower (since some additional debug paths are enabled)

3) Much more memory is used within the application at runtime

4) Scripts and images downloaded from the WebResources.axd handler are not cached

 

This last point is particularly important, since it means that all client-javascript libraries and static images that are deployed via WebResources.axd will be continually downloaded by clients on each page view request and not cached locally within the browser.  This can slow down the user experience quite a bit for things like Atlas, controls like TreeView/Menu/Validators, and any other third-party control or custom code that deploys client resources.  Note that the reason why these resources are not cached when debug is set to true is so that developers don’t have to continually flush their browser cache and restart it every-time they make a change to a resource handler (our assumption is that when you have debug=true set you are in active development on your site).

 

When <compilation debug=”false”/> is set, the WebResource.axd handler will automatically set a long cache policy on resources retrieved via it – so that the resource is only downloaded once to the client and cached there forever (it will also be cached on any intermediate proxy servers).  If you have Atlas installed for your application, it will also automatically compress the content from the WebResources.axd handler for you when <compilation debug=”false”/> is set – reducing the size of any client-script javascript library or static resource for you (and not requiring you to write any custom code or configure anything within IIS to get it).

 

What about binaries compiled with debug symbols?

 

One scenario that several people find very useful is to compile/pre-compile an application or associated class libraries with debug symbols so that more detailed stack trace and line error messages can be retrieved from it when errors occur. 

 

The good news is that you can do this without having the have the <compilation debug=”true”/> switch enabled in production.  Specifically, you can use either a web deployment project or a web application project to pre-compile the code for your site with debug symbols, and then change the <compilation debug=”true”/> switch to false right before you deploy the application on the server. 

 

The debug symbols and metadata in the compiled assemblies will increase the memory footprint of the application, but this can sometimes be an ok trade-off for more detailed error messages.

 

The <deployment retail=”true”/> Switch in Maching.config

 

If you are a server administrator and want to ensure that no one accidentally deploys an ASP.NET application in production with the <compilation debug=”true”/> switch enabled within the application’s web.config file, one trick you can use with ASP.NET V2.0 is to take advantage of the <deployment> section within your machine.config file.

 

Specifically, by setting this within your machine.config file:

 

<configuration>

    <system.web>

          <deployment retail=”true”/>

    </system.web>

</configuration>

 

You will disable the <compilation debug=”true”/> switch, disable the ability to output trace output in a page, and turn off the ability to show detailed error messages remotely.  Note that these last two items are security best practices you really want to follow (otherwise hackers can learn a lot more about the internals of your application than you should show them).

 

Setting this switch to true is probably a best practice that any company with formal production servers should follow to ensure that an application always runs with the best possible performance and no security information leakages.  There isn’t a ton of documentation on this switch – but you can learn a little more about it here.

 

Hope this helps,

 

Scott

 

Updated: Tess has a great follow-up post with more details about what happens when debug="true" is enabled.  You can read it here.

59 Comments

  • Scott, many thanks for the retail=&quot;true&quot; tip, we'll be implementing that right away!



    We currently use a web site project and use Publish Web Site to pre-compile it. I originally thought that this would automatically set debug=false in the web.configs it publishes but it does not. However, it does compile the site without any PDBs.



    Does this mean that only your point 4 is relevant if debug=true is left unaltered?



    Slightly off-topic - can you give an indication when the next release of the web application project will be available?



    Thanks

  • Does this also count for ASP.NET 1.1??

  • Hi Chris,



    The first three points all count for ASP.NET 1.1. The WebResource.axd handler isn't supported in V1.1 -- so that part is only V2.0 specific. I don't believe the &lt;deployment retail=&quot;true&quot;/&gt; switch was supported in V1.1.



    Hope this helps,



    Scott

  • Hi Scott,



    will the resources be cached on the local web browser without checking if there is a new file/version on the server, or will every request will get &quot;HTTP/1.0 304 Not Modified&quot; instead?



    Michael

  • Yes, good advice. One of my websites was running sooo slow and was already thinking of switching hosting providers, when I discovered that the site was running with Debug=true. Oops ;-)

  • In the documentation you link to about the deployment element, it notes that the custom error settings are disabled. Is this saying that my defaultRedirect or status code specific error pages will not work if I have them set in my web.config?



    Thanks,

    Gabe

  • Hi Gabe,



    Your custom errors will work fine with the retail switch set. I think what is disabled is the ability to turn customerrrors off -- meaning the ability to expose the raw exception to remote customers directy (which you want to make sure you never do with a production app).



    thanks,



    Scott

  • Hi Scott,



    When the Visual Basic Refactoring plugin is installed Visual Studio crashes almost every hour. When do you plan to update the plugin?



    Thank You

  • Hi Kevin,



    Can you send me email (scottgu@microsoft.com), and I can then loop you in with the VB team. Note that the plugin is not built by Microsoft (it is a third party component), but they can help you figure out how to get it fixed.



    Thanks,



    Scott

  • Scott,



    Thanks for all of your valuable insights. We are using the Web Deployment Project with the out of box Web Site configuration (ie. not Web Application Projects). I have the same issue as Brian's post about not being able to change the debug option to false in the Project settings. Any solution to this?



    Also, any word on when the final release of the Web Deployment Project add-in will be released?



    Thanks,

    Mike

  • Scott, thanks for the information! I knew it affect the performance. I have it on in the past in order to receive detailed error application message. According to you it's not worth so I turn it off. I do have the custom error page but I don't see the physical path to the error page through view&gt; source, with or without debug=&quot;true&quot; turn on.



    Sue

  • Hi Sue,m



    I believe the stack trace that Danny mentions above only happens if you are local on the machine. For remote access we never send the stack trace unless you have custom errors turned off.



    Hope this helps,



    Scott

  • Hi Michael,



    Good question about the caching. I think the client behavior depends on what your client is configured to-do with the browser. You can select either check for changes always, or just have it set to automatic.



    Hope this helps,



    Scott

  • This made a huge difference!!!



    Thanks!!

  • I have an even better reason to not deploy debug code. When you compile in debug mode, the PDB file includes references to the enviroment on which it was compiled. You will note that when an exception gets thrown in code that has debug mode on, it shows you the code that contains the error, as well as the path to the file. This path is always the location where the code was compiled, NOT the location where the code was running from.



    This has two problems 1) you reveal your dev landscape naming to anyone who sees the error, which could create some security problems



    2) More importantly, when an exception is thrown, the CLR tries to retrieve the code &quot;live&quot; from the location containted in the PDB. If you deploy debug code to production, it tries to retrieve the code from your dev server when the exception is thrown. It tries to log in to the dev server. The problem is that it logs into the dev server, using your production credentials (of the aspnet user) Assuming your password is not the same in prod and dev, it fails this authentication. If it gets a few errors in a row (3 on my server) the dev account gets locked out!



    Obviously this is only an issue if your prod server has network level connectivity to your dev server.

  • Good catch Tim -- I'll pass to the documentation team to get this fixed.



    Thanks,



    Scott

  • IS is possible in code to tell if I am under &quot;Debug=true&quot;? on the production server?

    IF so how?



    I think it would be nice if I could detect this in code and then send the webmaster an email to warn him about the issue?





    //Andy

  • Hi Andy,



    HttpContext.IsDebuggingEnabled comes close to that. It tells you whether debug is enabled in config for the current request. So if you override debug in sub dirs, this doesn’t necessarily match the application.



    Hope this helps,



    Scott

  • Caching doesn't seem to work for me. I have debug=&quot;false&quot; in web.config, cache set to &quot;automatic&quot; in IE 6, but Fiddler shows that WebResource.axd files are still getting downloaded without a 304 response from the server. What the hack am I doing wrong? Below is a line from fiddler showing the 200 response:



    Result Host URL Body CachingContent-Type User-defined

    5200 localhost /Main/WebResource.axd?d=Lx2tZgJ4CZYMCVBRSPKlzFU6GQN8tje_qDYAkRGohU_PNMQRZvviv5aGvpyf4x4c31VqrwggfhZInZA1QZ2ks4pWzVpDbf9eLwRHKPP0qrA1&amp;t=632796902540000000 23,612 public Expires: Sat, 21 Apr 2007 04:19:00 GMT text/javascript

  • Nevermind; I just realized that ctrl-r forces IE to discard cache and retrieve fresh content.

  • Hi Jeff,



    The cache header above says that it is being cached for 1 year (until April 2007). So I think the server is sending down the right stuff. My guess is that your browser is still requesting it for some reason (are you sure it isn't set to &quot;always&quot;?)



    Thanks,



    Scott

  • Hello Scott,



    I am loving the asp.net 20 and vs 2005 however

    no matter what I do I can't seem to get webresource.axd to work properly. The problem seems to occur when decrypting the framework javascript used for validation. What I am doing wrong here?

  • Hi David,



    Can you send me email (scottgu@microsoft.com) with more details of what you are running into?



    Thanks,



    Scott

  • To pre-compile the code for a site with debug symbols, I have to use the web application project model or create a new web deployment project? So is this not possible with an ASP.NET Web site? I'm a little frustrated with 2.0 because when I upgraded from 1.1, I've been forced to change every web project to the new web site model. This was a huge pain because an ASP.NET Web site is not precompiled into its own assembly and so I can't refer to its namespace. Now I have to change them back to get the benefits of debug=false with debug symbols included? My boss will not be impressed.

  • When we deploy our website using web deployment project, even in release mode (and YES debug="false" - in fact this is forced by deployment) we noticed that #If Debug statements in the code are still evaluating to TRUE! &nbsp;We can tell because of the verbose error messages. Any idea why this might be happening??

  • Hi MB,

    Can you send me an email (scottgu@microsoft.com) with more details on this? We can then figure out why this is happening.

    Thanks,

    Scott

  • This is cool but... whith https all resources wasn't cached.

  • Hi JJ,

    Correct -- the HTTPS protocol doesn't allow caching of resources client-side.

    Hope this helps,

    Scott

  • It's often noted that this impacts performance but not specifically why; thank you for the details. &nbsp;



    Can you confirm: I'm assuming that the Retail Deployment also overrides any @Page directives that may include Debug=&quot;true&quot;.

  • Hi Tyrven,

    Yep -- setting the retail flag should override the @Page directive as well.

    Hope this helps,

    Scott

  • Hi David:
    We just went ahead and turned off debugging on our ASP.Net 1.1 site written using Notepad :)
    I was wondering however, this still doesn&#39;t seem to have solved the problem. Is there anything else I can add/modify in the web.config file or somewhere else to speed up the site when that unfortunate user hits the page first and waits?? I am running the site on a Dual Xeon 3.0 with 2 GB running on SCSI RAID 5 hardware... So I think that&#39;s enough :)

  • Hi Russ,

    How many assemblies do you have within the application's \bin folder? And are you doing anything to load up data to cache on the first request?

    Given that hardware you shouldn't see much of a load time issue -- so it is odd that you are.

    Have you tried calling Microsoft support to have them help debug it?

    Thanks,

    Scott

  • i have been working with webresource.axd. It works ok, but when you use it over ssl (https) it doesn't work. It looks like asp.net can't send it to the browser (i mean, the resource, especially validators). It must be something i missed. But i cant find a solution. Can you advice me?

    Thanks,

    ram

  • Hi Ram,

    What you might be running into are cases where you have a mixed page -- with some resources over https and others over straight http.

    Is this the case?

    Thanks,

    Scott

    P.S. Note that you can use webresources.axd over https - that is supported.

  • we're having an issue where we get a secure nonsecure error on a checkout page that we want secured and found the culprit to be webresources.axd as it is the only thing making calls to port 80. but we are having a beast of time trying to figure out how to secure it. Any thoughts?

  • Hi JohnV,

    Can you send me email (scottgu@microsoft.com) with some more details about how your page is configured? I can then help you get this fixed.

    Thanks,

    Scott

  • Hi Scott,

    What if my I update my webapplication, will the resources also be updated? Will this be a problem if the client is using version 1.1 and I'm updating it to 1.2?

    Kristy

  • Hi Kristy,

    If you update your web application the resources should also be updated.

    Hope this helps,

    Scott

  • Scott! Very sober article indeed. I am using VS 2005 Web Application Model. I use the Build > Publish menu option to publish the entire application. Problem I have with this approach is that it restarts the application causing users to sign out. Is there any way I can avoid this by publishing only updated files? I am looking forward impateintly to your answer. Thanks in advance.

  • Hi Arif,

    When you update the .dll assemblies within the \bin directory, or update the web.config file of the application, the application will restart. This will cause in-memory session state to be lost - although forms-authentication tickets are not reset (so your users shouldn't be logged out).

    Hope this helps,

    Scott

  • Scott!

    I appreciate your reply. I agree with your answer. It means that when I publish my application on production server it not only restarts the application but also forces users to log out mainly because the session state is lost. So what is the industry standard solution to avoid this issue? Since I have to publish the fixes when there are users logged into my website. Does Visual Studio 2005 single file publish without publishing the entire project?

    Thanks a lot for your help.

  • Good post - Thanks Scott. But it doesn't discuss any potential issues with mixing debug settings at the web.config, page level, and in user controls. Are there any you know of?

    We've gotten this error that pops up after we have edited a commonly used user control in .Net 1.1 : "'mycontrol_ascx' is ambiguous in the namespace '_ASP'". I've seen a couple references to this issue on blogs, but no definitive response. I'm speculating it may be related to using Debug=True at the page level, but not on the user control or in web.config.

  • Hi Arif,

    What people typically do with updates is to perform them at certain non-peak times of the day (for example: in the evening or morning).

    Note that if you don't use session state, or use an out of process session state configuratiuon, there is no interruption to users.

    Hope this helps,

    Scott

  • Hi Brett,

    Can you send me an email with more details about the error you are seeing? I can then loop in a few folks to help investigate.

    Thanks,

    Scott

  • Can i change the web.config file line after publishing it to the server?

  • Hi Murali,

    Yes -- you can change this setting even after the app is published to the server.

    Thanks,

    Scott

  • Are you saying that even if I compiled the application using "release" instead of "debug" but leave the web.config set to debug=true that I will experience this sub-optimal performance?

  • Hi Mike,

    Yes -- you want to make sure you always set debug="false" in your web.config file. This prevents ASP.NET from running in debug mode and doing extra work.

    Thanks,

    Scott

  • Scott,

    We have a page containing a number of user controls and in the code behind we are looping through all the controls on the page and performing some actions depending on the type of the control. We are basing this on the following:

    select case aControl.GetType.ToString()

    case "ASP.OurControl_ascx"

    etc...

    Which has been fine on our development boxes, but when deployed to the production box with debug="false", the namespace seems to change to "_ASP". Why is this and is there any way around this?

  • Hi Paddy,

    I'd recommend definining an interface that you have your usercontrols or pages implemnet. You can then safely check for that at runtime.

    Hope this helps,

    Scott

  • Hi,

    Is there a way to do the same type of configuration in ASP.NET 1.1 ?

    Thanks

  • Hi Scott,

    Is there a way to achieve the same "restriction" using ASP.NET 1.1 ? I have many (150 !) applications in ASP.NET 1.1 and last week 2 of them forgott to change debug=true in their Web.config... As i'm running many applications in the same application pool 2 of them grow up to 1,5 GB ! Seems to be related to debug=true

    Regards
    Manu

  • Hi Manu,

    Unfortunately there isn't a way to automatically override this in ASP.NET 1.1. We added the feature in V2.0 after seeing people run into in it with 1.1.

    Hope this helps,

    Scott

  • Hi Paul,

    Have you tried calling Microsoft product support? They are great at debugging these types of issues, and should be able to figure out what is going on.

    Thanks,

    Scott

  • when i set debug=false then run build, the output window still tells me im building as debug?

    is this correct?

    Example:
    ------ Build started: Project: D:\...\eadweb\, Configuration: Debug .NET ------


  • Hi Mark,

    Unfortunately this is a bug with the information to the output window - it always says it is a debug configuration when building a web-site in the IDE.

    Sorry about that,

    Scott

  • Hi Ofer,

    Can you send me an email with more details on this issue? I can then have someone help debug it.

    Thanks,

    Scott

  • I've also recieved the "'mycontrol_ascx' is ambiguous in the namespace '_ASP'".

    The issue arose after setting debug="false" on our servers and we found the cause to be a second usercontrol with the same name. Maybe the debug="true" setting allowed these two usercontrols to be compiled and exist within separate dll's.

    The solution we used was to specify the ClassName attribute in the control directive for the usercontrol.

  • Scott,
    Can you give me one ideea why when I run the site using DNS as htpps://domain.com it runs very slow, but whern I use htpps://phisicalboxname.com it runs very fast. Of cause this is something I can do from our internal network but external users can't.

Comments have been disabled for this content.