As applications became more complex and started offering more configurable features, a natural progression was to use configuration files to store these values. It has since become a required feature of any application to support the use of configuration files to control various aspects of itself and to avoid hard-coding of variable data. Most Windows applications support this with the use of .ini files or entries in the Windows registry. ASP.NET includes this support by the use of machine.config and web.config files. These files are standard text files written using XML formatting and can be edited with any text editor such as Notepad or an XML parser. With the use of these files, ASP.NET provides the ability to modify many standard settings used within Web applications as well as allowing the creation of custom settings.
The configuration of a given Web application is computed in a hierarchical manner when the application is first accessed and then cached to speed up future references to the configuration.ASP.NET then monitors the configuration files for any changes, and if a change is detected, the cached configuration is flushed and recomputed.
In this chapter, we will go over the way ASP.NET uses its configuration files and how we can best take advantage of this feature. We will also discuss the application, system, and security aspects of the configuration files and work through the creation of a web.config file.
The configuration files used by ASP.NET are processed in a hierarchical manner. This means that the files located at a higher level of the hierarchy can override the options set within each file. An exception to this rule is provided to allow for locking down some settings. This exception uses the allowOverride attribute and the <location> tag to lock down the settings. The use of this option is explained in the “Anatomy of a Configuration File” section later in this chapter.
The machine.config file is used on a per-server basis and controls the base configuration of ASP.NET on the system. The machine.config is located in the C:\winnt\Microsoft.NET\Framework\version\CONFIG\ directory and is the highest-level configuration file. The web.config file can be located in your root application directory as well as in any subdirectories below it in order to set Web application specific configuration. If a value is not explicitly defined in a lower level configuration file and is defined in a higher-level file, the value will be inherited from the higher level configuration file. This process is outlined in Figure 4.1.
Figure 4.1 illustrates several important points regarding ASP.NET’s use of configuration files. Let’s walk through what this illustration shows.
First, the order in which the configuration files are processed is shown. The machine.config file is processed first. Any values specified within the machine .config file are inherited throughout every ASP.NET application on your Web server. The web.config file in each consecutive subdirectory is then processed with each lower-level file overriding the configuration files above it unless otherwise instructed.
Secondly, if a value is not explicitly defined in a lower-level configuration file, the value is inherited from the higher-level file. This is a very important feature to keep in mind as values set in a higher-level file may cause problems with an application stored at lower level.
Finally, we can see how the use of the allowOverride attribute affects an application’s configuration. The default value for the allowOverride attribute is true, which allows any lower level configuration file to override the configuration specified in a higher-level file. You can change this behavior by setting the allowOverride attribute to false, which prevents lower- level configuration files from overriding configuration options set at a higher level. If a lower-level configuration file attempts to override this setting, an error will occur. We will go into more detail on the allowOverride attribute for the <location> tag later in the chapter.
When examining the uses for ASP.NET’s configuration files, we must look at the machine.config file as well as the web.config file. The main difference between these two files is that the machine.config file is applied system-wide while the web.config is applied to each application based on the inheritance rules. Each configuration option set within the machine.config file is applied to every application and by using the allowOverride attribute in conjunction with the <location> tag; you can prevent individual web.config files from overriding these settings.
When ASP.NET is initially installed, a default machine.config file is set up for your system with the standard configuration section handlers used within ASP.NET as well as many other configuration items. You can edit this default file to tailor your ASP.NET configuration to your requirements. You can also configure the same options in the lower-level web.config files in order to give you more granular control over individual applications.
You can configure almost all functional items of ASP.NET through the configuration files. The options available to you using the default ASP.NET machine.config file include everything from browser compatibility options to secure authentication options. Table 4.1 details the standard tags available through the ASP.NET configuration files; however, you can define additional tags by defining new configuration section handlers.
|<sessionState>||Allows configuration of the session state HTTP module.||System|
|<trace>||Allows configuration of the ASP.NET trace service.||Application|
|<trust>||Allows configuration of the code access security permission set used to run your application.||Security|
|<webRequestModules>||Allows configuration of ASP.NET’s use of modules for request processing based on the prefix.||System|
|<webServices>||Allows configuration of ASP.NET Web Services settings.||System|
Each standard tag in Table 4.1 has been categorized as belonging to one of these three configuration groups, and we will review each option and its function in the following sections. Many of these tags do overlap between the configuration groups, but this breakdown serves as a general guideline for defining your configuration.
The <appSettings> tag supports only two attributes, a key and a value. This setting enables you to set static variables for your application. One excellent use for this configuration setting is to set all of your application specific variables in a single location. This gives you the ability to completely control your application through a single configuration file. In previous ASP versions, these options were set through the use of application variables, but ASP.NET’s utilization of this feature is much more efficient. The following code shows the use of this tag in setting a data source name for your application.
The <globalization> tag enables you to configure your application to accept requests or respond to requests using different encoding options. Using this configuration setting will allow your site to respond in the specific encoding used by any country accessing your site. The default for requestEncoding and responseEncoding within the machine.config file is utf-8 for English-language systems, and if this setting is removed, ASP.NET defaults to your system’s locale setting. This tag supports five attributes as shown in Table 4.2.
|requestEncoding||Specifies the assumed encoding for incoming requests.|
|responseEncoding||Specifies the encoding for Web application responses.|
|fileEncoding||Specifies the default encoding for .aspx, .asmx, and .asax file parsing.|
|culture||Specifies the default culture for processing incoming requests.|
|uiCulture||Specifies the default culture for processing locale-dependent resource searches.|
The <identity> tag enables you to configure the application identity for your Web application. You can then use this identity throughout your application for access to resources without explicitly including the user id and password elsewhere. This can be very useful when accessing a remote database or databases. You also have the option of setting the application identity to impersonate the client. The default within the machine.config is to set the impersonate attribute to false. The <identity> tag supports only three attributes. The impersonate attribute can be set to either true or false. If the impersonate attribute is false, you can set the userName and password attributes to a specific user id and password for your application to use. This is shown in the following code example:
The <pages> tag presents several page-specific attributes that you can configure. These are used to set response buffering options, session, and view states, code-behind classes, and page events options. By changing these options, you can control the way pages act within your site. As an example, if you wish to disable page events, you can set the autoEventWireup tag to false. These attributes and their options are detailed in Table 4.3.
The <trace> tag enables you to configure the ASP.NET tracing service. By enabling this service, you are able to obtain extensive debugging information about your application. This is extremely useful when you are developing an application and want to view all of the information related to the compile or other trace information. This tag supports five attributes as detailed in Table 4.4.
The description field in Table 4.4 shows the default settings for the <trace> tag in ASP.NET’s machine.config. The code below is an example of how to enable tracing and append it to the page output.
The system configuration options are generally best applied when set in the machine.config and applied system-wide. Most of these options control the way ASP.NET itself functions, and enables you to add additional system-level capabilities to your application. In some cases, these configuration options are restricted as to what level they can be applied at. As we examine each option, the levels at which the option is applicable will be defined.
The <browserCaps> tag enables you to configure the browser capabilities component. This tag enables you to determine the type and version of browser and operating system that the remote client is using and define the capabilities that the client has based on this information. Using this enables you to tailor your dynamic page to only include features that the browser is capable of using. For example, if you’re using tables within your document and the browser doesn’t support tables, the document could end up formatted differently than what you intended. By using this, you would never have sent a table to the browser. The actual data used to obtain this information is pulled by using the HTTP_USER_AGENT variable. You can specify this by using the <use> subtag with the <browserCaps> tag. The <result>, <filter>, and <case> subtags are supported in order to populate the <browserCaps> attributes. The settings for most major browsers currently on the market are defined in the default ASP.NET machine.config file. These attributes are detailed in Table 4.5 along with the input data types that they support.
You set all of ASP.NET’s compilation options by using the <compilation> tag. This allows for a very detailed level of control over the compilation of your application. The default settings in the machine.config are usually sufficient for most applications. The only time when these options would need to be changed would be to modify the compilation of your ASP.NET application. The <compilation> tag supports seven attributes and three subtags. The attributes are explained in Table 4.6.
The <compilation> tag also supports three subtags: <compilers>, <assemblies>, and <namespaces>. Each of these supports its own subtags in order to give a more granular level of control over the compilation options.
The <compilers> subtag exists only to encapsulate one or more <compiler> subtags. This subtag is used to define a new compiler option. The <compiler> subtag supports five attributes, which are illustrated in Table 4.7.
|language||Specifies a list of language to be used within dynamic compilation files. You can specify multiple languages by separating them with semicolons.|
|extension||Specifies file extensions used for dynamic code-behind files. You can specify multiple extensions by separating them with semicolons.|
|type||Specifies a class/assembly combination that indicates the .NET Framework class used to compile all resources using the specified language(s) or extension(s). You can specify multiple classes by separating them with semicolons.|
|warningLevel||Specifies compiler warning levels for the specified type.|
|compilerOptions||Any additional compiler-specific options that need to be passed to the .NET Framework class are specified with this attribute.|
The <assemblies> subtag enables you to specify ASP.NET processing directives. It supports three subtags that act as the processing directives: <add>, <remove>, and <clear>. The use of these three subtags is detailed in Table 4.8.
|<add>||Enables you to add an assembly reference for use when a dynamic resource is compiled. This assembly is automatically linked to the resource by ASP.NET when each code module is compiled. The <add> subtag uses the same attributes and syntax as the AssemblyName class.|
|<remove>||Enables you to remove an assembly reference previously specified by using the <add> tag. The assembly name used in the <remove> tag must match the name used in the <add> tag, and wildcards are not supported.|
|<clear>||Removes all assembly references whether they were explicitly defined or inherited.|
The <namespaces> subtag enables you to specify additional ASP.NET processing directives. The subtags supported by the <namespaces> subtag are identical to the <assemblies> subtag and perform the same function, using namespaces instead of assemblies.
The <connectionManagement> tag enables you to control the number of simultaneous connections allowed per address on your system. By using this tag, you can control the optimization of your pages. As an example, if you want to speed up access to a smaller number of users, then increase the number of simultaneous connections. This tag supports the <add>, <remove>, and <clear> subtags. The <add> subtag specifies the address(es) to set connection limits on. It has two attributes, address and maxconnection. Proper usage of the <add> subtag is illustrated in the following code sample. The <remove> subtag only accepts the address attribute and is used to remove addresses previously specified with the <add> subtag. Wildcards are also supported with the <remove> tag. The <clear> subtag removes all addresses from the configuration whether explicitly defined or inherited.
By using the <customErrors> tag, you have the ability to define custom error messages for your application. This is generally used to point users to a friendlier message than the default error messages. This tag supports only two attributes and one subtag. The two attributes supported are defaultRedirect and mode. The defaultRedirect attribute accepts a string value representing the default URL to redirect the browser to when an error occurs. The mode attribute has three options: On, Off, and RemoteOnly. These options allow you to enable or disable custom error support or enable custom error support only for remote clients.
The <error> subtag supported by the <customErrors> tag enables you to set pages to redirect specific errors to. The <customErrors> tag supports the use of multiple <error> subtags, enabling you to redirect many different errors to the appropriate URL. The usage of these tags are outlined in the following code example:
The <httpHandlers> tag is used to map incoming requests to the appropriate IHttpHandler or IhttpHandlerFactory class. This is done based on the URL requested and the verb used to request it. Some example verbs used by this are GET, POST, and PUT. You would use this if you had a custom handler that you wanted to implement when files with a certain extension are requested. As an example, you could use this if you had a custom virus scanner needed to be run against all files sent with a PUT request that have the .ZIP extension. You could develop a custom handler to do this and assign the handler to the .ZIP extension in combination with the PUT verb. This can also be used to restrict certain files from being viewed, by pointing them to the System.Web.HttpForbiddenHandler handler. The <httpHandlers> tag supports three subtags to control this configuration option: <add>, <remove>, and <clear>.
The <add> subtag is used to add new entries to the list and supports three attributes. The first is the verb attribute, which specifies specific verbs to apply this IHttpHandler or IhttpHandlerFactory to. This attribute does accept wildcards. The second attribute is path, which specifies either a specific URL path or a wildcard string. The final attribute is type, which specifies the class/assembly combination. ASP.NET has a specific search order for finding the appropriate DLL. It first checks in the application’s “bin” directory, and then in the system assembly cache.
The <remove> subtag accepts only the path and type attributes and is used to remove a previously specified mapping from the list. The <clear> subtag removes all mappings from the list whether they are explicitly defined or inherited.
The <httpModules> Tag enables you to configure the HTTP modules used within your application. This tag supports the <add>, <remove>, and <clear> subtags. The <add> subtag specifies the HTTP module class to add to your application. It has two attributes, type and name. Proper usage of the <add> subtag is illustrated in the following code sample. The <remove> subtag accepts the same attributes of type and name and is used to remove HTTP modules previously specified with the <add> subtag. Wildcards are also not supported with the <remove> tag. The <clear> subtag removes all addresses from the configuration whether explicitly defined or inherited.
The <httpRuntime> tag enables you to set various runtime options for ASP.NET’s HTTP processing. These options are represented by the three available attributes for the <httpRuntime> tag. By changing these attributes, you can control the way ASP.NET functions when performing operations requested by the user.
The first attribute is useFullyQualifiedRedirectUrl. This attribute supports a boolean value of true or false, and configures whether ASP.NET uses fully qualified client-side redirects or relative redirects. The default is false, which specifies relative redirects. Fully qualified redirects are only used for some mobile controls or very early-stage Web browsers.
The second available attribute is executionTimeout, which specifies the maximum amount of time that a request is allowed to process before being terminated by ASP.NET. This is used both to terminate hung applications as well as to prevent badly coded applications from using up all your system resources. This attribute accepts a numeric value specified in seconds.
The final attribute for the <httpRuntime> tag is maxRequestLength. This attribute specifies a maximum file size that ASP.NET will accept as an upload. This is primarily used to prevent users from performing a denial of service attack by uploading large files to your server. In addition, it can help manage your disk capacity by limiting the size of the files your server accepts. This attribute accepts a numeric value in megabytes. These attributes are illustrated in the following code:
The <processModel> tag is used to set various options for the ASP.NET process model. These options are represented by the 15 attributes supported by the <processModel> tag and are described in Table 4.9. The <processModel> tag can only be used within the machine.config file.
The <sessionState> tag enables you to configure the session state HTTP module. This tag supports five attributes, which are detailed in Table 4.10. For further information on session state, please refer to Chapter 5.
The <webRequestModules> tag enables you to configure the request modules used within your application. These modules control the way that ASP.NET will respond to different requests. As an example, one of the default modules is the System.Net.FileWebRequestCreator module. Whenever a request prefaced with “file://” is sent to the server, the System.Net.FileWebRequestCreator module is called to handle the request.
This tag supports the <add>, <remove>, and <clear> subtags. The <add> subtag specifies the request module class to add to your application. It has two attributes, prefix and type. Proper usage of the <add> subtag is illustrated in the following code sample. The <remove> subtag accepts the same attributes of prefix and type and is used to remove request modules previously specified with the <add> subtag. Wildcards are not supported with the <remove> tag. The <clear> subtag removes all request modules from the configuration whether explicitly defined or inherited.
The <webServices> tag enables you to configure aspects of ASP.NET’s web services and how they function. Web services are explained in detail in Chapter 10. By using various subtags, you can add protocol types, writer and reader types, as well as configure many other options. All of the subtags supported by the <webServices> tag support the three attributes of add, remove, and clear. There are two different styles of subtags supported, standard subtags, and type subtags. When using a standard subtag, the add and remove attributes use the name value. When using a type subtag, these attributes use the type value.
There are many subtags supported by the <webServices> attribute. Table 4.11 contains a partial list of these subtags and describes the style of each subtag.
Security is a very important area of configuration for ASP.NET. The tags provided in this section enable you to configure several aspects of ASP.NET security including encryption and authentication. When planning any application, you should always keep security in mind and make sure that all aspects of your application are as secure as possible. These tags, when configured properly, can assist in reaching the goal of a secure application.
Authentication refers to the portion of ASP.NET, which verifies that the users accessing your application are indeed who they say they are. This should be used to verify the identity of your users for security reasons as well as personalization of the application. The mode attribute specifies the type of authentication to use. Table 4.12 shows the available options for this attribute and what they mean. When Windows authentication is referred to, this includes all forms of authentication supported by IIS such as basic, digest, NTLM/kerberos, or certificates.
|Windows||Specifies Windows/IIS authentication mode.|
|Forms||Specifies an ASP.NET forms-based authentication mode.|
|Passport||Specifies the use of Microsoft Passport authentication mode.|
|None||No authentication specified. This should only be used for anonymous access-based applications or applications designed with their own authentication scheme.|
The <authentication> tag also supports two subtags, <forms> and <passport>. The <forms> tag is used to specify configuration information for using ASP.NET’s forms-based authentication mode. This subtag supports five attributes and one subtag. These attributes are shown in Table 4.13.
The <forms> subtag supports the <credentials> subtag. This subtag enables you to specify user id and password credentials within the configuration file. This is done by using the passwordFormat attribute and the <user> subtag. The passwordFormat attribute accepts three values, which specifies the password encryption. These values are as follows:
The second subtag supported by the <authentication> tag is <passport>. This subtag has a single attribute of redirectUrl, and enables you to specify a default URL to redirect the user to if the passport mode is used and the user has not signed on with passport. The following code sample shows the use of these options:
The <authenticationModules> tag enables you to add or remove the security modules used within ASP.NET for authentication. This will only be used if you wish to add some other form of authentication to ASP.NET. This may evolve in the future with the use of smart cards and biometric authentication. This tag supports the <add>, <remove>, and <clear> subtags. The <add> subtag specifies the authentication module class to add to your application. It uses the type attribute to specify the class. Proper usage of the <add> subtag is illustrated in the following code sample. The <remove> subtag accepts the same attribute of type and is used to remove authentication modules previously specified with the <add> subtag. Wildcards are not supported with the <remove> tag. The <clear> subtag removes all authentication modules from the configuration whether explicitly defined or inherited.
The <authorization> tag is used to control access to specific resources based on permissions granted to the user or role. For any application, you want only authorized users to access your application in certain ways. Historically this has been controlled by the use of user databases, but for small applications this works well. In addition, if a method of access is needed, should the backend database fail, this provides a good failsafe.
This is done by using the two subtags, <allow> and <deny>. The <allow> subtag controls which users or roles are granted access, and the <deny> subtag controls which users or roles to which access is denied. Both subtags support the same three attributes. These are described in Table 4.14. All permissions specified through this configuration are read and applied by ASP.NET from the top down; therefore the order in which you specify your permissions is very important.
|users||Enables you to designate a list of users to either be allowed or denied access. User names should be separated with a comma. The ? and * symbols are used to specify anonymous or all users, respectively.|
|roles||Enables you to designate a list of roles to either be allowed or denied access. You should separate roles with a comma.|
|verbs||Enables you to specify a list of verbs to either allow or deny access to. These include GET, HEAD, POST, and DEBUG. You should separate verbs with a comma.|
The <machineKey> tag enables you to configure encryption keys for use with encryption and decryption of forms authentication cookie data. This is very important to use when high security is necessary for your application. When this is in place, cookies used for forms authentication are encrypted. Forms authentication is explained in the earlier section of this chapter on the <authentication> tag. The <machineKey> tag supports three attributes as shown in Table 4.15.You can specify this tag on any level with exception of the subdirectory level.
|validationKey||AutoGenerate/value||Specifies the key used for validation.|
|decryptionKey||AutoGenerate/value||Specifies the key used for decryption.|
|validation||SHA1/MD5/3DES||Specifies the type of encryption being used for validation.|
As shown in Table 4.15, the validationKey and decryptionKey attributes can either be set to AutoGenerate a key or have a specific value set. This value must be at least 40 characters long and have a maximum limit of 128 characters. The recommended length is 128 hexadecimal characters, for maximum security. If you are using multiple Web servers with your application in a Web farm environment, these keys must match between all Web servers. If you use AutoGenerate with a Web farm, your keys will not match, and your application will not work correctly. The following sample code illustrates the usage of this tag.
The <securityPolicy> tag enables you to map policy files to specific security level names. By doing so, you can then easily implement your own custom security configuration throughout your application. This tag accepts the subtag of <trustLevel>. Multiple <trustLevel> subtags can be placed within a <securityPolicy> tag. The <trustLevel> subtag accepts two attributes, name and policyFile. The name attribute is used to specify a logical name to designate the policy, and the policyFile attribute specifies the policy file. The default names set up with ASP.NET are Full, High, Low, and None. The following code shows these names as well as one custom name and their associated policy files:
The <trust> tag enables you to apply specific trust levels to your application. By using this tag, you are able to use security policy files with your Web applications. This tag accepts only two attributes, level and originUrl. The level attribute is used to reference a trust level previously specified with the <trustLevel> tag. The originUrl tag specifies an application’s origin URL. This is used for certain permissions that allow connectivity back to the origin host, such as Socket and WebRequest. If the permissions that you are applying require a host to function correctly, then you must specify this attribute. The use of this tag is illustrated in the following code:
The machine.config and web.config files are written using standard XML formatting. These files consist of a hierarchy of tags and subtags. Each tag or subtag contains attributes that contain the actual configuration values. All of the tags, subtags, and attributes in the configuration files are case-sensitive, and your application will generate errors if a tag or attribute is formatted incorrectly.
Fortunately, there are specific rules that XML uses to help in getting the case correct. All tags, subtags, and attributes are camel-cased, which means that the first “word” of the name is lower case and any additional “words” in the name are capitalized. For example, take the tag <webRequestModules>. This tag consists of the three words: web, request, and modules. The first word is all lower case, and the remaining two are capitalized.
XML, much like HTML, requires that each tag have a beginning and an end. This can be accomplished within a single statement by opening the tag and closing with a “/>” at the end. The example code for the <machineKey> tag uses this method:
When a tag contains subtags, you cannot begin and end a tag within the same statement. You must use a separate beginning and ending tag in this situation. A good example for this is the <configuration> tag itself:
The first part of the machine.config file is the definition of configuration section handlers. These are the classes used by the tags within the rest of the configuration file to apply configuration settings. The default configuration section handlers are detailed in the previous section, so we are now going to look at how to create additional handlers. These are generally created in the machine.config file for use between all applications, but can also be created within web.config files for application-specific configuration section handlers.
You can create your own .NET Framework class for this by creating a class that supports the IconfigurationSectionHandler interface. For our example, we will be using the System.Configuration.NameValueFileSectionHandler class, which is the same class used by the <appSettings> tag.
All configuration section handlers are specified within the <configSections> tag. They are then defined by using the <section> tag. This tag accepts the name and type attributes. The name attribute specifies the tag that you will later be using to reference this class, and the type attribute contains the actual class/assembly combination.
In addition, you can group configuration section handlers into sections by using the <sectionGroup> tag. This tag accepts the name attribute, which specifies the tag you will later use to reference this section. So, we can put this all together as shown in the following sample code:
We have one more tag to go over before we go through the creation of a configuration file. This tag is the <location> tag and is used to designate certain configuration options to apply only to specific files or directories. This tag can also be used to lock down configuration options so that they cannot be changed at a lower level. The <location> tag accepts the path and allowOverride attributes. The path attribute enables you to specify a location to apply a set of configuration options to. If you are using the <location> tag within a machine.config file, the path attribute can specify either virtual directories or applications. If you are using it within a web.config file, the path attribute enables you to specify a directory, subdirectory, application, or file. The allowOverride attribute accepts a value of either true or false and enables you to lock down the configuration options. This tag is illustrated in the following code sample:
At this point, we’ve covered the default tags provided with ASP.NET, learned how to create our own configuration section handlers, and have gone over how to assign configuration options to specific locations. Now, let’s create a configuration file for an application. We’ll call our application “TestConfig” and store it within its own virtual directory to avoid inheriting any configuration other than the machine.config.
We’ll start off our web.config file by opening the <configuration> tag and defining a new configuration section handler. We’ll place this handler within a new section group, just in case we need to add more handlers to the application at some point in the future.
Now let’s assume that we have another page within our application located in a subdirectory that should use different settings for its tables. We also want to lock this setting down so that it can’t be changed by a web.config file that another developer may place in the subdirectory. We’ll accomplish this by using the <location> tag:
We want to make sure that this page uses resource buffering as well as the session and view states. We also want to enable page events automatically. These should be all the special configuration options that we need to specify for this application, so we’ll also go ahead and close our <location> tag as well.
Let’s also set our application to require Windows authentication, and allow access only to a couple of individuals for testing purposes. Just to be sure, we’ll also explicitly deny access to everyone else.