The configuration information for an ASP.NET application is stored in one or more XML-based configuration files named
Web.config. The default configuration settings for all web applications on the web server are spelled out in the
Web.config file in the
$WINDOWS$\Microsoft.NET\Framework\version\CONFIG folder. These default settings can be added to over overridden for a specific web application by the
Web.config file in that application’s root directory. Moreover, these configuration settings can be customized for a web application on a folder-by-folder basis by adding
Web.config files to the application’s subfolders.
Web.config file spells out an array of configuration settings, including: database connection strings, authentication and URL authorization rules, and the behavior that unfolds when an unhandled exception occurs, among many others. Many configuration settings differ between the development environment and the production environment. For example, when you are developing an ASP.NET application on your desktop you are likely using a different database than when the application is in production. Consequently, the database connection strings in
Web.config need to be updated when deploying an application.
Some of these types of configuration settings must be changed when deploying an application, like database connection strings. Failure to modify the configuration information when deploying will cause the web application not to work in production. These types of configuration settings are easy to remember to change. But there are a number of configuration settings that should be changed when deploying an application, but if they are not changed the application will still work in production. These configuration settings are easy to forget to change, and forgetting to change them can reduce the performance of your application or make it more vulnerable to attacks from malicious users. This article details a handful of configuration settings that fit into this latter category.
Enabling Custom Errors
In .NET applications, an illegal operation – an invalid cast, attempting to reference a null value, trying to connect to a database that’s been taken offline, and so on – raises an exception. Exceptions can be caught and handled directly in code through the use of
Try / Catch blocks. For ASP.NET applications, if the exception is not handled in code, it bubbles up to the ASP.NET runtime, which raises an
HttpUnhandledException. How the ASP.NET runtime responds to an
HttpUnhandledException depends on your application’s configuration settings. The runtime will do one of three things:
- Display a generic error page that simply reports that a runtime error has transpired,
- Display an error page with error details, including the exception that was raised and, if the code is compiled with debug symbols, a stack trace and a few lines of code around where the exception was thrown.
- A custom error page, which is an ASP.NET page that you create that the user is redirected to.
Web.config file contains a
<customErrors> element that dictates which of the three outcomes detailed above unfolds in the face of an unhandled exception. The
mode attribute of the
<customErrors> element can have one of three values:
On– the “Runtime Error” page or custom, user-friendly error page is shown to all visitors in the face of an unhandled exception.
Off– the exception details page is shown to all visitors in the face of an unhandled exception.
remoteOnly– remote users – those not coming through localhost – see the “Runtime Error” page or custom, user-friendly error page; local visitors – the developers, typically – see the exception details page.
When an unhandled exception occurs in a production environment it is important that the user not see the exception details page, for such information could constitute a security risk. For instance, the line of code where the exception was raised might include sensitive information in the source code, such as an ad-hoc SQL query or, even worse, a database connection string. Even if the code shown in the exception details page doesn’t reveal any such tidbits, by showing the details of the exception you are revealing some of the inner workings of how your application works to the visitor. This may give a malicious visitor additional information on how to compromise your application. Furthermore, the exception details page is ugly a bewildering to most users. It’s best to show them a custom error page whose look and feel mimics the look and feel of your website.
Turn Off Output Tracing
Output tracing enables developers to display request information at the bottom of a page or from a special URL,
Trace.axd. Tracing can be configured at the page-level through the
Trace attribute in the
@Page directive, or can be configured for the entire web application using the
<trace> element in
Having tracing enabled in a production environment is ill advised because the trace log displays sensitive information including cookies, information stored in session state, and any diagnostic information written to the trace log. With tracing enabled, a malicious user could visit the
Trace.axd page and see the trace logs for the last several requests to the application.
To prevent trace information from appearing in a production website you can either disable tracing altogether or configure it so that it’s only accessible when coming through localhost. The
<trace> element has two Boolean attributes that specify these particular settings:
localOnly. For more information see the
<trace> element technical documentation and Tracing in ASP.NET.
Turn Off Debugging Support
When an ASP.NET page is visited for the first time or for the first time after it has been modified, the declarative markup in the page is automatically compiled into a class and is then “executed” by the ASP.NET runtime in order to generate the content to return to the requesting client. This conversion from declarative markup to source code, and the source code’s compilation, is seamlessly handled by the ASP.NET runtime when the request is made. Various settings regarding this compilation process can be configured via the
<compilation> element in
Web.config. Furthermore, the source code in the ASP.NET pages’ code-behind classes can either be compiled automatically by the web server or explicitly by the developer before deployment. If you build your application using Visual Studio’s Web Site Project model and deploy the code files (rather than a compiled assembly) then you are using the automatic compilation model, and the
<compilation> element’s settings also apply to the auto-compilation of the code-behind classes.
<compilation> element includes a
debug attribute that indicates whether to compile the code in debug mode or in retail mode. Code compiled in the debug mode includes addition debug symbols and other performance-draining information that is required during debug time. For applications in the development environment, where you will actively be debugging your application, it makes sense to have the
debug attribute set to true. But when deploying your application, make sure you set this attribute to false. Doing so will improve the performance of your application by more quickly compiling these resources and using less memory when a page is visited.
For a more detailed discussion of this configuration setting and why it should be set to false, see Scott Guthrie‘s blog entry, Don’t run production ASP.NET Applications with
debug="true" Enabled. In it, Scott lists four effects of having the
debug attribute set to true:
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
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 [ASP.NET AJAX], 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).”
To get optimal performance from your website, make sure that the
Web.config file in production has the
debug attribute set to false.
Forcing Deployment Configuration Best Practices Using the
<deployment retail="true" /> Setting
If you are deploying your web application to a machine that you have control over, such as a web server within your company’s intranet or a dedicated web server at a web host provider, you can use the
<deployment> element in
machine.config to force all applications on the web server to adhere to the recommendations provided above (namely, using a custom error page, disabling output tracing, and not having the auto-compiled code compiled in debug mode). Simply add the following markup to the
machine.config file within the
<deployment retail="true" />
Note: You’ll find the
machine.config file in the
That’s all there is to it! To undo this setting, you can remove this element or set the
retail attribute to false (the default). Keep in mind that the
<deployment> element can only appear in
machine.config, and not
Web.config, and applies to all websites on the server.
There are a variety of configuration settings relevant for an ASP.NET application, and some of these settings should differ based on whether the application is in a development environment or a production environment. This article looked at three configuration settings that do not need to be changed when deploying an application, but definitely should be changed for performance- and security-related reasons. If you have control over the web server you can force these best practice configuration settings by adding
<deployment retail="true" /> to the server’s