ASP.NET provides a very powerful and flexible means of configuring applications. This configuration is accomplished using text-based XML configuration files. The server-wide configuration file is called machine.config , described in Section 20.3.1. This is supplemented by a number of application-specific configuration files, all called web.config , located in the application virtual root directory and subdirectories.
This configuration scheme offers the following features:
The XML files that control the configuration can be edited with any standard text editor or XML parser. It is not necessary to use the IIS control panel, as was the case with classic ASP.
Since the configuration is accomplished with text files, it is easy to administer remotely. Files can be created or edited remotely, then copied into place via FTP or remote network access by anyone with suitable security clearance. There is no need for a person to be physically present at the server machine hosting the application in order to perform configuration chores, as is the case with classic ASP.
The system is hierarchical. Each application inherits a baseline configuration from machine.config, located on the server. The web.config files then apply successive configuration attributes and parameters as the application directory tree structure is traversed. This will be explained in detail in Section 20.3.1.
A corollary of the hierarchical nature of the system is that each application can have its own independent configuration. It is not necessary for all applications to share a server-wide configuration, as with classic ASP.
The system is extensible. The baseline system provides configurability to a large number of standard program areas. In addition, you can add custom parameters, attributes, and section handlers, as required by your application. This too will be explained in detail below.
It is possible to modify the configuration of a running application without stopping and restarting either the application or the server. The changes automatically and immediately apply themselves to any new client requests. Any clients online at the time the changes are made will not be aware that changes are being made, other than perhaps a slight delay for the first request made after the change is put in place.
The configuration settings for each unique URL are computed at application runtime, using all the hierarchical web.config files. These configuration settings are then cached so that requests to each URL can retrieve the configuration settings in a performant manner. ASP.NET automatically detects if any configuration files anywhere in the hierarchy are modified, and recomputes and recaches the configuration settings accordingly.
Configuration files are hidden from browser access. If a browser directly requests a configuration file in a URL, an HTTP access error 403 (forbidden) will be returned. This is the same behavior seen if the global.asax file is requested directly by a browser.
The configuration system is hierarchical, just as a directory tree structure is hierarchical. The file at the very top of the hierarchy is a file called machine.config . This file is contained in the subdirectory:
c:winntMicrosoft.NETFrameworkversion number
CONFIG
where version
number
will be replaced with the version
of the .NET runtime installed on your machine, such as
v1.0.2914
.
All the other configuration files are called web.config . These files are optional: if there are none anywhere in an application virtual directory or its subdirectories, then the configuration settings contained in machine.config will apply to your application without any modifications.
Each directory and subdirectory contained in the application can have at most a single web.config file. The configuration settings contained in a specific instance of web.config apply to the directory in which it is contained and to all its child directories. If a specific instance of web.config contains a setting that is in conflict with a setting higher up in the configuration hierarchy (i.e., in a parent directory or machine.config ), then the lower-level setting will override and apply to its own directory and all child subdirectories below it (unless, of course, any of those child subdirectories have their own copies of web.config, which will further override the settings).
So for example, consider the directory structure shown in Figure 20-5. The virtual root of the web site is called MyWebSite, corresponding to the physical directory c:inetpubwwwrootMyWebSite. Underneath the virtual root are two child subdirectories, each of which has additional child subdirectories. The URL for this web site would be www.MyWebSite.com (assuming that the domain name MyWebSite.com was registered to the IP address assigned to the server).
If there were no web.config files in any of these directories, then all the configuration would come directly from machine.config. If there is a version of web.config in the directory MyWebSite, then any settings it contains would apply to the entire application (but only to that application), including all the subdirectories beneath it. If there were another version of web.config in the MembersOnly directory, then its configuration settings would apply to the MembersOnly directory and its subdirectories, but not to PublicStuff. If any of the settings in web.config in MembersOnly conflicted with those in MyWebSite, then the settings in MembersOnly would override those in MyWebSite.
It is important to note that the hierarchical nature of the configuration files is based on application virtual directories first, and then physical directories. Refer again to Figure 20-5. The only virtual directory defined so far for that application is MyWebSite. However, suppose another virtual directory, MyPublicWebSite, were defined, corresponding to c:inetpubwwwrootMyWebSitePublicStuff. The URL for this application would be www.MyPublicWebSite.com. This application would inherit the configuration settings from machine.config, but not from c:inetpubwwwrootMyWebSiteweb.config. Although c:inetpubwwwrootMyWebSite is the physical parent directory of c:inetpubwwwrootMyWebSitePublicStuff, it is not the virtual parent. In fact, c:inetpubwwwrootMyWebSitePublicStuff is a virtual root and does not have a parent. Configuration settings inherit from virtual parents, not physical parents.
The configuration files, machine.config
and
web.config
, are XML
files. As such they must be well formed. (For a description of well
formed XML, see the sidebar Well-Formed HTML in Chapter 4.)
Specifically, these files consist of a nested hierarchy of
XML
tags. All opening tags must have the corresponding closing tag or be
self-closing (with a trailing /
character just
inside the closing angle bracket). The tag pairs must not be
interleaved with other tag pairs. Subtags may be nested inside tag
pairs. Both tags and subtags may have attributes and attribute
values. All of these elements are case-sensitive.
Typically, tag and attribute names consist of one or more words run together. Tag and attribute names are camel-cased. Attribute values are usually Pascal-cased.
Camel-casing
means that all the characters are
lowercase, including the first character, except the first character
of each run-on word after the first. Examples of camel-casing are
appSettings
, configSections
,
section
, and sessionState
.
Pascal-casing
is the same as camel-casing except that
the first character of the name is also upper case. Examples of
Pascal-casing are SortByTime
,
InProc
, and StateServer
.
The word usually is used because there are exceptions:
true
and false
are always
lowercase.
Literal strings do not adhere to either camel- or Pascal-casing. For
example, a database connection string may be specified as:
SERVER=Zeus;DATABASE=Pubs;UID=sa;PWD=secret;
If the value is the name of another tag in a configuration file, then it will be camel-cased.
The first line in the configuration file declares the file to be an XML file, with attributes specifying the version of the XML specification to which the file adheres and the character encoding used. Here is a typical XML declaration line:
<?xml version="1.0" encoding="UTF-8" ?>
The character encoding specified here is UTF-8, which is a superset of ASCII. The character encoding parameter may be omitted if, and only if, the XML document is written in either UTF-8 or UTF-32. Therefore, if the XML file is written in pure ASCII, the encoding parameter may be omitted, although including the attribute contributes to self-documentation.
The next line in the configuration files is the opening
<configuration>
tag:
<configuration>
The entire contents of the configuration file, except the initial XML
declaration, is contained between the opening
<configuration>
tag and the closing
</configuration>
tag.
Comments can be contained within the file using the standard XML (and HTML) format:
<!-- Your comments here -->
Within the <configuration>
tags are two
broad categories of entries. They are, in the order in which they
appear in the configuration files:
The
handler declarations are
contained between an opening
<configSections>
tag and a closing
</configSections>
tag. Each handler
declaration specifies the name of a configuration section, contained
elsewhere in the file, that provides specific configuration data.
Each declaration also contains the name of the .NET class that will
process the configuration data in that section.
This terminology is very confusing. The first part of the file is
enclosed in <configSections>
tags, but
contains only a list of the configuration sections and their
handlers, not the configuration sections themselves. And as you will
see shortly, the configuration sections are each contained within
tags, but there is no grouping tag to contain all the separate
configuration sections, analogous to
<configSections>
.
The machine.config file contains, in the default installation, many configuration section handler declarations that cover the areas subject to configuration by default. (Since this is an extensible system, you can also create your own. A typical entry containing a handler declaration is shown in Example 20-12.
In the original machine.config file, the contents of Example 20-12 were all contained in a single line.
Example 20-12. Typical configuration section handler declaration
<section name="compilation" type="System.Web.UI.CompilationConfigurationHandler, System.Web, Version=1.0.2411.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
Despite appearances to the contrary, the
<section>
tag has only two attributes:
name
and type
. The
name
is compilation
. This
implies that somewhere else in the configuration file is a
configuration section called compilation
. This
configuration section will contain the configuration settings, which
are name/value pairs, to be used by the application(s). It will be
described in detail shortly.
The type
attribute has a lengthy parameter
enclosed in quotation marks. This parameter contains:
The class that will handle the named configuration section
The assembly file (DLL) that contains that class
Version and culture information to coordinate with the assembly file
A public key token used to verify that the DLL being called is secure
Each handler need only be declared once, either in the base level machine.config file or in a web.config file further down the configuration hierarchy. The configuration section it refers to can then be specified as often as desired in other configuration files.
Example 20-13 shows a truncated version of the default machine.config .
Only a small subset of the actual entries in machine.config are included in Example 20-13. Also, the type
attribute
of each entry has been edited to remove all but the class, and lines
have been broken to enhance the readability.
Example 20-13. Truncated machine.config file
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <configSections> <section name="runtime" type="System.Configuration.IgnoreSectionHandler" /> <section name="mscorlib" type="System.Configuration.IgnoreSectionHandler" /> <section name="startup" type="System.Configuration.IgnoreSectionHandler" /> <section name="appSettings" type="System.Configuration.NameValueSectionHandler " /> <sectionGroup name="system.net"> <section name="defaultProxy" type="System.Net.Configuration.DefaultProxyHandler " /> </sectionGroup> <sectionGroup name="system.web"> <section name="compilation" type="System.Web.UI.CompilationConfigurationHandler " /> <section name="pages" type="System.Web.UI.PagesConfigurationHandler " /> </sectionGroup> </configSections> <appSettings> <!-- use this section to add application specific configuration example: <add key="XML File Name" value="myXmlFileName.xml" /> --> </appSettings> <system.net> <defaultProxy> <proxy usesystemdefault="true" /> </defaultProxy> <webRequestModules> <add prefix="http" type="System.Net.HttpRequestCreator" /> <add prefix="https" type="System.Net.HttpRequestCreator" /> <add prefix="file" type="System.Net.FileWebRequestCreator" /> </webRequestModules> </system.net> <system.web> <compilation debug="false" explicit="true" defaultLanguage="vb"> <compilers> <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider " /> <compiler language="vb;visualbasic;vbscript" extension=".vb" type="Microsoft.VisualBasic.VBCodeProvider " /> <compiler language="js;jscript;javascript" extension=".js" type="Microsoft.JScript.JScriptCodeProvider " /> </compilers> <assemblies> <add assembly="mscorlib"/> <add assembly="System "/> <add assembly="System.Web "/> <add assembly="System.Data "/> <add assembly="System.Web.Services "/> <add assembly="System.Xml "/> <add assembly="System.Drawing "/> <add assembly="*"/> </assemblies> </compilation> <pages buffer="true" enableSessionState="true" enableViewState="true" enableViewStateMac="false" autoEventWireup="true" /> </system.web> </configuration>
The first three declarations in machine.config are
runtime
,
mscorlib
, and
startup
. They are special because they are
the only declarations that do not have corresponding configuration
sections in the file.
In Example 20-13, you can also see that many of the
handler declarations are contained within
<sectionGroup>
tags. The name
attribute
of these tags corresponds to the namespace that contains the
handlers. This groups together all the configuration sections that
are handled out of the
same
namespace.
The configuration sections contain the actual configuration data. They each are contained within a pair of tags corresponding to the name of the section specified in the configuration section handler declaration. Alternatively, a single self-closing tag can be used. For example, the following two configuration sections are equivalent:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
and:
<globalization> requestEncoding="utf-8" responseEncoding="utf-8" </globalization>
Configuration sections contain name/value pairs that hold the configuration data. They may also contain subsections.
machine.config
contains one configuration section
for each handler declaration. If the handler declaration was
contained within a <sectionGroup>
tag, then
its corresponding configuration section will be contained within a
tag containing the name of the
<sectionGroup>
. This can be seen in Example 20-13 for both system.net
and
system.web
.
The sections that follow provide a description of each of the
configuration sections contained in the default machine.config. There are other configuration
sections that are beyond the scope of this book, including
system.diagnostics
,
system.runtime.remoting
, and
system.windows.forms
.
appSettings
allows
you to easily store application-wide name/value pairs for read-only
access. It is similar in function to application objects in the
global.asax file.
The handler declaration for appSettings
, shown in
Example 20-13 and reproduced here:
<section name="appSettings" type="System.Configuration.NameValueSectionHandler " />
indicates that the NameValueSectionHandler class is used to
handle appSettings
. This class provides name/value
pair configuration handling for a specific configuration section.
As seen in Example 20-13, the
appSettings
section in the default machine.config file contains only a comment.
More typically, you would add an appSettings
section to one or more web.config
files.
Example 20-14 shows a web.config
file with an
appSettings
section added to provide two
application-wide values. Note that the appSettings
section is not contained within any higher-level tag other than
<configuration>
.
Example 20-14. appSettings configuration section
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="appDSN" value=" SERVER=Zeus;DATABASE=Pubs;UID=sa;PWD=secret;" /> <add key="appTitle" value="Programming ASP.NET" /> </appSettings> </configuration>
These values can be accessed anywhere in the application to which this configuration is applicable (i.e., its current directory and any child directories in which the value is not overridden by another web.config file). Example 20-15 and Example 20-16 show a script block from an .aspx file to illustrate how this is done in both VB.NET and C#, respectively. The C# version of the code in Example 20-16 shows only the script block, since the HTML is identical to the VB.NET version in Example 20-15.
Example 20-15. Reading appSettings values in VB.NET
<%@ Page Language="vb" %> <script runat="server"> sub Page_Load(ByVal Sender as Object, _ ByVal e as EventArgs) if not IsPostBack then dim strDSN as string strDSN = ConfigurationSettings.AppSettings("appDSN") ' use the DSN to connect to the database here lblDSN.Text = strDSN lblTitle.Text = ConfigurationSettings.AppSettings("appTitle") end if end sub </script> <html> <body> <form runat="server"> <h1>Configuration</h1> Application DSN: <asp:Label id="lblDSN" runat="server"/> <br/> Application Title: <asp:Label id="lblTitle" runat="server"/> </form> </body> </html>
Example 20-16. Reading appSettings values in C#
<%@ Page Language="cs" %> <script runat="server"> void Page_Load(Object Source, EventArgs E) { if (!IsPostBack) { string strDSN; strDSN = ConfigurationSettings.AppSettings["appDSN"]; // use the DSN to connect to the database here lblDSN.Text = strDSN ; lblTitle.Text = ConfigurationSettings.AppSettings["appTitle"]; } } </script>
Configuration settings are read by an application using the AppSettings property of the ConfigurationSettings class. This class provides methods and properties for reading configuration settings in an application’s configuration files. It is part of the System.Configuration namespace, which is automatically imported into every ASP.NET application.
The AppSettings property of the ConfigurationSettings class is of type NameValueCollection. It takes a key as a parameter and returns the value associated with that key.
The
system.net
configuration section contains subsections that deal with the .NET
runtime. These subsections include
authenticationModules
,
defaultProxy
,
connectionManagement
, and
webRequestModules
. These subsections are not
normally used by developers and are outside the scope of this book.
The
system.web
configuration section contains subsections that configure ASP.NET.
Each of these subsections will be described briefly in the following
sections.
This subsection contains information about the capabilities of all the web browsers and operating systems your clients are likely to use. This information includes such items as the name of the browser; its major and minor version numbers; whether it supports frames, tables, cookies, cascading style sheets, VBScript, JavaScript, Java applets; and so on.
The version of <browserCaps>
contained in
the default machine.config file
performs fairly extensive testing of the client browser to determine
both the browser capabilities and the client platform.
As new browser versions come on the market, you can update the information contained in this section by visiting http://www.cyscape.com/browsercaps/.
Closely related to
<browserCaps>
, the
<clientTarget>
subsection provides ASP.NET
with aliases for the
browsers. For example, it provides the
aliases shown in Table 20-2.
This subsection allows you to
configure the compilation behavior in ASP.NET. For example, you can
change the default language and enable or disable debugging. If the
default language is VB.NET, you can also set the
explicit
attribute to true
,
which is the equivalent of including the Option
Explicit
On
statement in your
page or web service.
The default <compilation>
tag in machine.config looks like this:
<compilation debug="false" explicit="true" defaultLanguage="vb">
In a VB.NET project created in Visual Studio .NET, the default
<compilation>
tag in the web.config file for the application looks
like this:
<compilation defaultLanguage="vb" debug="true" />
and for a C# project in Visual Studio .NET, it looks like this:
<compilation defaultLanguage="c#" debug="true" />
Notice that the debug
attribute in either
web.config file overrides the
value set in machine.config.
In addition to setting the language and debug mode, this subsection
includes two other subsections:
<compilers>
and
<assemblies>
. The former subsection specifies what
language names map with what file extensions. It also specifies the
class containing the code provider and version information. The
latter subsection specifies which assembly files are to be included
when the project is compiled.
This subsection specifies
whether page options, such as buffering, session state, and view
state, are enabled for the pages under the control of the
configuration file. The default <pages>
tag
in the default machine.config
file looks like:
<pages buffer="true" enableSessionState="true" enableViewState="true" enableViewStateMac="false" autoEventWireup="true" />
The
autoEventWireup
attribute
is specific to Visual Studio .NET. If set to true
,
then Visual Studio .NET can automatically hook up event handlers on
controls when the control is double clicked in design mode. If set to
false
, then you must manually hook up the event
handlers.
This subsection allows you to
control what the user sees when there is an error. Example 20-17 shows a typical
<customErrors>
configuration section that
demonstrates the available features.
Example 20-17. <customErrors> configuration section
<customErrors defaultRedirect="StdError.htm" mode="RemoteOnly" > <error statusCode="404" redirect="err404.htm" /> <error statusCode="407" redirect="err407.htm" /> </customErrors >
When custom errors are enabled, if an error occurs, the web page
specified in
defaultRedirect
is
presented to the client rather than the standard ASP.NET error page.
The mode
attribute specifies how custom errors
are enabled. There are three possible values for this mode, which are
shown in Table 20-3.
Table 20-3. Values for the mode attribute of the <customErrors> tag
Value |
Description |
---|---|
|
Custom errors are enabled. |
|
Custom errors are disabled. |
Custom errors are shown only to remote clients, not to local clients. This setting allows developers to see the full error message provided by ASP.NET while still showing end users the error page you wish them to see. |
You can add multiple
<error>
tags to present
specific error pages for specific errors.
In Example 20-17, error 404 will result in err404.htm being presented to the client, error 407 will result in err407.htm, and all other errors will result in StdError.htm being presented. In any case, the developer working on the local machine will see none of these custom error pages, but rather will see the standard error page put up by ASP.NET.
This subsection configures the ASP.NET HTTP runtime settings. There are several attributes available in this section; they are shown in Table 20-4.
Table 20-4. Attributes of the httpRuntime subsection
Attribute |
Description |
---|---|
Specifies if client-side redirects are fully qualified, which is
necessary for some mobile controls. Legal values are
| |
Maximum number of seconds a request is allowed to execute before being shut down by ASP.NET. | |
Maximum file size for upload, in bytes. This can help prevent denial of service attacks by preventing clients from posting large files. | |
Minimum number of free threads for execution of new requests. These threads are available for requests that require additional threads. | |
Minimum number of free threads available for requests to localhost. | |
Maximum number of requests queued waiting for a free thread. If incoming request rejected, then “503 Server too busy” error will be returned. |
The <httpRuntime>
tag in the default
machine.config file looks like:
<httpRuntime executionTimeout="90" maxRequestLength="4096" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="10" />
This subsection is used to configure the globalization settings for an application. The attributes shown in Table 20-5 are supported.
Table 20-5. Attributes of the globalization subsection
Attribute |
Description |
---|---|
Specifies the encoding assumed for incoming requests. If not specified in any configuration file, defaults to computer’s Regional Options locale setting. | |
Specifies the encoding of responses. If not specified in any configuration file, defaults to computer’s Regional Options locale setting. | |
Specifies the default encoding for parsing .aspx, .asmx, and .asax files. | |
Specifies the default culture for incoming requests. | |
Specifies the default culture for locale-dependent resource searches. |
The <globalization>
tag in the default
machine.config file looks like:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
This subsection maps incoming
requests to a class that implements either the
IHttpHandler
or
IHttpHandlerFactory
interfaces. There is a fairly
extensive mapping in the default machine.config file, which maps standard file
types to a specific class (e.g., all .aspx requests are mapped to the
PageHandlerFactory class).
The <httpHandlers>
tag has several subtags:
<add>
Specifies the mapping. A typical
<add>
subtag looks like:
<add verb="*" path="*.vb" type="System.Web.HttpForbiddenHandler"/>
The verb
attribute can either contain a comma
separated list of HTTP verbs, such as GET, PUT, or POST
, or the wildcard character (*
). The
path
attribute can contain either a single URL
path or a wildcard string. The type
attribute is a
class name. ASP.NET first searches for the specified class in the
in directory, then in the
global assembly cache. (See Section 20.4 later in this chapter for a
description of the global assembly cache.)
<remove>
Removes a previously added mapping. It
has the same syntax as the <add>
subtag,
except that there is no type
attribute.
<clear>
Clears all currently configured or inherited mappings. It has no attributes.
This subsection configures the
HTTP modules within an application. Each
<add>
subtag within the subsection assigns a
class to a module. The default machine.config file includes the modules and
their classes shown in Table 20-6.
This tag configures the process
model settings on an IIS web
server. The <processModel>
tag in the
default machine.config file looks
like this:
<processModel enable="true" timeout="Infinite" idleTimeout="Infinite" shutdownTimeout="0:00:05" requestLimit="Infinite" requestQueueLimit="5000" restartQueueLimit="10" memoryLimit="60" webGarden="false" cpuMask="0xffffffff" userName="machine" password="AutoGenerate" logLevel="Errors" clientConnectedCheck="0:00:05" comAuthenticationLevel="Connect" comImpersonationLevel="Impersonate" />
For a detailed description of each of these attributes, consult the SDK documentation.
The <sessionState>
tag
configures
session state. Session state is covered fully in Chapter 6. This tag supports the attributes shown in
Table 20-7.
Table 20-7. Attributes of the <sessionState> tag
Attribute |
Description |
---|---|
Specifies where the session state is stored. It has four legal
values. | |
Specifies whether cookieless sessions should be used. A value of
| |
The number of minutes a session is idle before it is abandoned. The default is 20. | |
Specifies the connection string to the server where session is to be
stored if | |
Specifies the connection string to the SQL Server where session is to
be stored if |
The default <sessionState>
tag in
machine.config is shown here:
<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" stateNetworkTimeout="10" sqlConnectionString="data source=127.0.0.1;user id=sa;password=" cookieless="false" timeout="20" />
The <trace>
tag configures the ASP.NET
trace service. Tracing is described fully in Chapter 7. The <trace>
tag
supports the attributes shown in Table 20-8.
Table 20-8. Attributes of the <trace> tag
Attribute |
Description |
---|---|
Enables or disables tracing. Legal values are | |
The number of trace requests to store on the server. | |
| |
Specifies the sort order of the trace display.
| |
|
The default <trace>
tag in machine.config is shown here:
<trace enabled="false" localOnly="true" pageOutput="false" requestLimit="10" traceMode="SortByTime" />
The <webControls>
tag specifies
the location of the script that is generated to be run client-side.
It supports a single attribute,
clientScriptsLocation
.
The default <webControls>
tag in machine.config is shown here:
<webControls clientScriptsLocation="/aspnet_client/{0}/{1}/" />
The <webServices>
tag configures
web services.
The default <webServices>
tag in machine.config is shown here:
webServices> <protocols> <add name="HttpSoap"/> <add name="HttpPost"/> <add name="HttpGet"/> <add name="Documentation"/> </protocols> <soapExtensionTypes> </soapExtensionTypes> <soapExtensionReflectorTypes> </soapExtensionReflectorTypes> <soapExtensionImporterTypes> </soapExtensionImporterTypes> <wsdlHelpGenerator href="DefaultWsdlHelpGenerator.aspx" /> <serviceDescriptionFormatExtensionTypes> </serviceDescriptionFormatExtensionTypes> /webServices>
Many aspects of ASP.NET security are configurable, using the machine.config and web.configfiles. For a complete discussion of the security concepts configured here, please see Chapter 19.
There are several configuration sections controlling security. They are described in the following sections.
The <identity>
tag controls the identity
of the application at runtime. Specifically, it enables and disables
impersonation, and if impersonation is enabled, it allows you to
specify the userName and password to use.
The <identity>
tag supports three attributes
shown in Table 20-9.
The <identity>
tag in the default
machine.config file looks like
this:
<identity impersonate="false" userName="" password=""/>
The <authentication>
tag controls authentication in ASP.NET
applications. As is described fully in Chapter 19,
authentication is the process whereby ASP.NET security verifies that
a client making a request is who they say they are.
The <authentication>
tag has one
attribute, mode
,
which specifies the default authentication mode for the application.
There are four legal values for mode
, which are
shown in Table 20-10.
Table 20-10. Values of the <authentication> tag’s mode attribute
Mode value |
Description |
---|---|
Sets the default authentication mode to Windows. Using this mode allows IIS to perform authentication. | |
Sets the default authentication mode to Forms. Using this mode, your application controls authentication through a login form created as part of the application. | |
Sets the default authentication mode to Passport. Passport is a centralized authentication service offered by Microsoft. | |
No authentication will be performed. This means that only anonymous users will access the site or the application will provide its own authentication. |
The <authentication>
tag also has two
subtags. They are <forms>
and
<passport>
.
The <forms>
tag has five
attributes, listed in Table 20-11.
Table 20-11. Attributes of the <forms> tag
Attribute |
Description |
---|---|
Specifies the name of the HTTP cookie used for authentication. The
default name is | |
Specifies the URL to which the request is redirected if there is no valid authentication. | |
Four legal values. | |
The integer number of minutes after the last request that the cookie
expires. Does not apply to persistent cookies. Default value is
| |
Specifies the path for cookies. Default value is |
The <forms>
tag also has one subtag,
<credentials>
. This subtag allows you to
specify the type of password encryption used and also to define
name/password pairs within the <user>
subtag.
The <credentials>
tag has a single
attribute,
passwordFormat
. This attribute has three legal
values, which are shown in Table 20-12.
The <credentials>
tag enables you to specify
user/password pairs using the
<user>
subtag. The
<user>
subtag has two attributes:
name
and
password
. Their values
are the username
and password
,
respectively.
The <passport>
subtag of the
<authentication>
tag has a
single attribute,
redirectUrl.
The value of this attribute is the
URL to redirect to if the page requires authentication and the user
has not signed on with Passport.
The <authentication>
tag in the default
machine.config file looks like
this:
<authentication mode="Windows"> <forms name=".ASPXAUTH" loginUrl="login.aspx" protection="All" timeout="30" path="/" > <credentials passwordFormat="SHA1"> <!-- <user name="UserName" password="password"/> --> </credentials> </forms> <passport redirectUrl="internal" /> </authentication>
The <authorization>
tag controls authorization
in ASP.NET applications. Authorization is how ASP.NET security
controls access to URL resources.
The <authorization>
tag
supports two
subtags, <allow>
and
<deny>
. Both subtags have the same set of
three attributes, which are shown in Table 20-13.
Those attributes are used to define access rules that are iterated at
runtime. Access for a particular user is allowed or denied based on
the first rule found that fits that user.
Table 20-13. Attributes of the <allow> and <deny> subtags
Attribute |
Description |
---|---|
Comma-separated list of users either allowed or denied access.
Question mark ( | |
Comma-separated list of roles that are allowed or denied access. | |
Comma-separated list of HTTP verbs that are allowed or denied access.
Registered verbs are |
The default <authorization>
tag in
machine.config is shown here. It
allows all users.
<authorization> <allow users="*" /> </authorization>
The <machineKey>
tag configures keys used
for encryption and decryption of authentication
cookies. This section can be declared
at the server level in machine.configor in web.config
files at
the site or application root level. The
<machineKey>
tag supports three attributes,
which are shown in Table 20-14.
Table 20-14. Attributes of the <machineKey> tag
Attribute |
Description |
---|---|
Specifies the key used for validation. Supports two types of values:
| |
Specifies the key used for decrypting the cookie. Uses the same
values as the | |
Specifies the type of encryption used for data validation. There are
three legal values: |
The default authorization in machine.configis shown here:
<machineKey validationKey="AutoGenerate" decryptionKey="AutoGenerate" validation="SHA1"/>
The <securityPolicy>
tag maps named security levels to policy
files. This section can be declared at the server level in
machine.config or in web.config
files
at the site or application root level.
The <securityPolicy>
tag supports one
subtag, <trustLevel>
. This subtag is used to
specify one security level name and an associated policy level. There
is a separate <trustLevel>
tag for each
named security level.
The <trustLevel>
tag supports the two
attributes shown in Table 20-15.
Table 20-15. Attributes of the <trustLevel> tag
Attribute |
Description |
---|---|
Defines a name to associate with the specified level of trust. Legal
values are | |
Specifies the policy level, relative to the directory containing machine.config, associated with the specified level of trust. |
The default <securityPolicy>
in machine.config is shown here:
securityPolicy> <trustLevel name="Full" policyFile="internal" /> <trustLevel name="High" policyFile="web_hightrust.config" /> <trustLevel name="Low" policyFile="web_lowtrust.config" /> <trustLevel name="None" policyFile="web_notrust.config" /> /securityPolicy>
The <trust>
tag configures the code access security
permissions for an application. This section can be declared at the
server level in machine.config or
in web.confi
g
files at the site
or application root level.
The <trust>
tag supports the two attributes
shown in Table 20-16.
The default <trust>
in
machine.config
is shown here:
<trust level="Full" originUrl="" />
The
location
section is
used to apply configuration settings to specific resources. The
<location>
tag has a single attribute,
path
. The
path
attribute
specifies a file or child directory (relative to the location of the
current web.config
file) to which specific configuration
settings apply.
Suppose you had an application with custom error pages specified in the web.config file in the application virtual root directory. These custom error pages would apply to the entire application, including all child directories. Suppose further that there are two subdirectories under the virtual root directory, called sub1 and sub2. sub1 is to have the application-wide custom error handling, but sub2 is to have its own specific error handling.
You could put another copy of web.config in sub2 to override the custom error handling,
but an alternative would be to use the
<location>
tag. You would add the following
lines to the web.config file in
the virtual root of the application:
<location path="sub2"> <system.web> <customErrors defaultRedirect="Sub2Error.htm" mode="RemoteOnly" > <error statusCode="404" redirect="err404-sub2.htm" /> <error statusCode="407" redirect="err407-sub2.htm" /> </customErrors > </system.web> </location>
Notice that the <system.web>
tag must be
reproduced within the location
section.
The configuration settings contained in a location
section will apply to the directory specified in the path attribute
and also to any child directories of that directory, unless they are
further overridden either by another web.config file or another
location
section.
If you want to apply specific configuration settings to a single
file, that too can be done using a location
section. Suppose the application root had a web page that requires
special error handling. The following location
section will accomplish that.
<location path="SpecialPage.aspx"> <system.web> <customErrors defaultRedirect="SpecialError.htm" mode="RemoteOnly" > <error statusCode="404" redirect="err404-spcl.htm" /> </customErrors > </system.web> </location>
In addition to all the predefined configuration sections, you can also add your own custom configuration sections. There are two different types of custom configuration sections you might wish to add:
Sections that provide access to a collection of name/value pairs,
similar to appSettings
Sections that return any type of object
Both will be demonstrated here.
Back in Example 20-14, youadded an
<appSettings>
key to store the database DSN
string. Suppose you wanted to store DSNs for multiple databases, say
one called Test (for testing purposes) and one called Content (to
hold the production content). A custom configuration section
returning a name/value pair would be one way to handle this
situation.
The finished version of lines of code inserted into web.config is shown in Example 20-18. There are several steps to adding a custom configuration section that returns a name/value pair:
Determine which specific configuration file to add the custom section to. This will determine the scope, or visibility, of the custom section.
Adding the section to machine.config will make it available to every application on that machine. Adding it to a web.config file in the virtual root directory of an application will make the section visible to that entire application, but to no other applications. Adding it to a web.config file in an application subdirectory will make it visible only to that subdirectory and its child subdirectories.
Declare the section handler by adding a line to the
<configSections>
section of the designated
configuration file. This tells ASP.NET to expect a configuration
section with the specified name, and also which class and assembly
file to use to process the section.
Add the highlighted lines between the
<configSections>
tags in Example 20-18 to the designated configuration file. If the
file you are editing does not already have a pair of
<configSections>
tags, then you will need to
add those as well.
Add the custom section itself to the configuration file. This
consists of the highlighted lines in Example 20-18
between the <altDB>
tags.
This custom configuration section contains two entries, one named
Test and the other named Content, each with its own
value
attribute.
Example 20-18. Custom sections in web.config
<configSections><section name="altDB"
type="System.Configuration.NameValueSectionHandler, System" />
</configSections><altDB>
<add key="Test"
value=" SERVER=Zeus;DATABASE=Test;UID=sa;PWD=secret;" />
<add key="Content"
value=" SERVER=Zeus;DATABASE=Content;UID=sa;PWD=secret;" />
</altDB>
Note that the type
in the
<section>
tag is exactly the same as that
provided for appSettings
in the
machine.config file. It specifies the
NameValueSectionHandler class in the
System.dll assembly
file.
To read the contents of this custom configuration section, you again use a method from the ConfigurationSettingsclass, this time the GetConfig method. The code for a sample web page for doing this is shown in Example 20-19 in VB.NET and in Example 20-20 in C#. The C# version of the code in Example 20-20 shows only the script block, since the HTML is identical to the VB.NET version in Example 20-19.
Example 20-19. Reading custom configuration values in VB.NET, vbConfig-02.aspx
<%@ Page Language="vb" %> <script runat="server"> sub Page_Load(ByVal Sender as Object, _ ByVal e as EventArgs) if not IsPostBack then dim strTest as string dim strContent as string strTest =ConfigurationSettings.GetConfig("altDB")("Test")
lblTest.Text = strTest lblContent.Text = _ConfigurationSettings.GetConfig("altDB")("Content")
end if end sub </script> <html> <body> <form runat="server"> <h1>Configuration</h1> <b>Test Database DSN: </b> <asp:Label id="lblTest" runat="server"/> </br> <b>Content Database DSN: </b> <asp:Label id="lblContent" runat="server"/> </form> </body> </html>
Example 20-20. Reading custom configuration values in C#, csConfig-02.aspx
<%@ Page Language="cs" %> <script runat="server"> void Page_Load(Object Source, EventArgs E) { if (!IsPostBack) { string strTest; string strContent;strTest = ((NameValueCollection)
ConfigurationSettings.GetConfig("altDB"))["Test"];
lblTest.Text = strTest;lblContent.Text = ((NameValueCollection)
ConfigurationSettings.GetConfig("altDB"))["Content"];
} }</script>
The code in Example 20-19 and Example 20-20 shows two equivalent ways of displaying the contents of the key value. One way is to assign the value to a string, then assign the string to the Text property of a label. The other way is to assign the value directly to the Text property. Although the latter technique is more concise, the former is often easier to debug.
In either case, notice the highlighted code in Example 20-19 and Example 20-20. These are the calls to the GetConfig method. They are different for VB.NET and C#, and a bit confusing in both.
The GetConfig method takes a configuration section name as a parameter and returns an object of type NameValueCollection. The desired value in the collection is retrieved by using the key as an offset into the collection, using the get property syntax. In VB.NET, a property is retrieved by enclosing the property name in parentheses, and in C#, the property is retrieved using square brackets.
Notice that the C# code first casts, or converts, the value returned
by GetConfig to type NamedValueCollection, while VB.NET does not.
This is because C# does not support late binding, while VB.NET does
by default. You can disable late binding in VB.NET (almost always a
smart move) by setting the Strict
attribute to
true
in the Page
directive. You
must then explicitly cast the object returned by GetConfig, just as
in C#. This is shown in Example 20-21.
Example 20-21. Reading custom configuration values in VB.NET using early binding, vbConfig-02b.aspx
<script runat="server"> sub Page_Load(ByVal Sender as Object, _ ByVal e as EventArgs) if not IsPostBack then dim strTest as string dim strContent as string strTest = _ CType(ConfigurationSettings.GetConfig("altDB"), _ NameValueCollection)("Test") lblTest.Text = strTest lblContent.Text = _ CType(ConfigurationSettings.GetConfig("altDB"), _ NameValueCollection)("Content") end if end sub </script>
appSettings
and custom
configuration sections are very useful. However, they both suffer
from the same limitation of only being able to return a name/value
pair. Sometimes it would be very useful to return an object.
For example, suppose you have a standard query into a database. You
could store the query string in an appSettings
tag, then open a database connection after retrieving the string.
However, it would be much more convenient to store the query string
in web.config and then have the
configuration system return a DataSet directly.
To do this, you must add a <section>
tag and
a configuration section to the designated configuration file, just as
with the custom section returning name/value pairs, described in the
previous section.
Edit the web.config file used in the previous example and shown in Example 20-18, adding the lines of code highlighted in Example 20-22.
Example 20-22. Custom sections returning objects in web.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="altDB" type="System.Configuration.NameValueSectionHandler, System" /><sectionGroup name="system.web">
<section name="DataSetSectionHandler"
type="ProgAspNet.Handlers.DataSetSectionHandler,
vbSectionHandlers">
</section>
</sectionGroup>
</configSections> <appSettings> <add key="appDSN" value=" SERVER=Zeus;DATABASE=Pubs;UID=sa;PWD=secret;" /> <add key="appTitle" value="Programming ASP.NET" /> </appSettings> <altDB> <add key="Test" value=" SERVER=Zeus;DATABASE=Test;UID=sa;PWD=secret;" /> <add key="Content" value=" SERVER=Zeus;DATABASE=Content;UID=sa;PWD=secret;" /> </altDB> <system.web><!-- Custom config section returning an object -->
<DataSetSectionHandler str="Select BugID, Description from Bugs" />
</system.web> </configuration>
In the
<sectionGroup>
section within the
<configSections>
section, a handler declaration is created for the
DataSetSectionHandler
within the
system.web
group.
This specifies that elsewhere within the file, there will be a custom
configuration section called DataSetSectionHandler
within the system.web
custom section. Furthermore,
it also specifies that the class that will handle that configuration
section is called ProgAspNet.Handlers.DataSetSectionHandler, and that
the class will be found in an assembly file called vbSectionHandlers.dll in the in directory.
Further down in the file, within the
<system.web>
section, there is in fact a
section called DataSetSectionHandler
. It has a
single attribute, str
. This is a string containing
the SQL statement you wish to pass to the database.
Next you must create the ProgAspNet.Handlers.DataSetSectionHandler class and place it in a file called DataSetSectionHandler.vb. To do this, create a VB.NET source code file as shown in Example 20-23.
Example 20-23. Source code for section handler in VB.NET, DataSetSectionHandler.vb
Imports System Imports System.Data Imports System.Data.SqlClient Imports System.XML Imports System.Configuration Namespace ProgAspNet.Handlerspublic class DataSetSectionHandler : _
Implements IConfigurationSectionHandler
public Function Create(parent as Object, _
configContext as Object, _
section as XmlNode) as Object _
Implements IConfigurationSectionHandler.Create
dim strSql as string strSql = section.Attributes.Item(0).Value dim connectionString as string = "server=Ath13; uid=sa; " & _ "pwd=password; database=Bugs" ' create the data set command object and the DataSet dim da as SqlDataAdapter = new SqlDataAdapter(strSql, _ connectionString) dim dsData as DataSet = new DataSet( ) ' fill the data set object da.Fill(dsData,"Bugs") return dsData end Function end class end NameSpace
Be sure to set the connection string to match your specific database. The server name and password are certainly different than that shown in Example 20-23.
The database aspects of the code in this example are covered thoroughly in Chapter 11 and won’t be covered here in detail.
At the beginning of the Example 20-23 are several
Imports
statements (if written in C#, these
would be using
statements). Next a namespace is declared
to contain the class. This is to prevent any ambiguity when calling
the class.
In order for a class to be
used as a configuration section handler, it must be derived from the
IConfigurationSectionHandler
interface. In VB.NET, this is
implemented by using the Implements
keyword. (In
C#, this would be indicated with a colon between the class or method
name and the class or interface being inherited.)
A full discussion of object-oriented concepts such as inheritance, base classes, and interfaces is beyond the scope of this book. For now, you should just know that an interface acts as a contract that the implementing class must fulfill. The interface may, for example, dictate the signature of methods that the implementing class must implement, or it may dictate which properties the class must provide.
The IConfigurationSectionHandler
interface has
only a single method,
Create.
Therefore our implementing class must implement the Create method
with the specified signature. The three parameters are dictated by
the interface. The first two parameters are rarely used and will not
be further discussed here. The third parameter is the XML data from
the configuration file.
The XML node is parsed and the value of the first item in the Attributes collection is assigned to a string variable in this line:
strSql = section.Attributes.Item(0).Value
Once the SQL string is in hand, the connection string is hard-coded,
a SqlDataAdapter
object is instantiated and executed, and
the DataSet is filled. Then the DataSet is returned.
Before this class can be used it must be compiled. Open a command
prompt by clicking on the Start button, then Microsoft Visual Studio
.NET → Visual Studio .NET Tools →
Visual Studio .NET Command Prompt. Use the cd
command to make the application virtual root the current directory.
This assumes that the virtual root directory already has a child
directory called bin. If not,
you’ll have to make one. Then enter the following
command line:
vbc /t:library /out:binvbSectionHandlers.dll /r:system.dll,System.data.dll,System.xml.dll DataSetSectionHandler.vb
Using command-line compilers is explained in some detail in Chapter 16. Here the target type of output is set to be
library
, i.e., a DLL. The name of the output file
to be placed in the bin directory will be vbSectionHandlers.dll. Notice that three DLL
files are referenced. The input source file is DataSetSectionHandler.vb. When the source
file is compiled, you will have the output DLL in the in
directory, where
the classes it contains will automatically be available to the
application.
The web page shown in Example 20-24 (in VB.NET) shows how to utilize this configuration section.
Example 20-24. Section handler demonstration in VB.NET, vbConfig-03.aspx
<%@ Page Language="vb" %> <%@ Import namespace="System.Data" %> <%@ Import namespace="System.Data.SqlClient" %> <script runat="server"> sub Page_Load(ByVal Sender as Object, _ ByVal e as EventArgs) if not IsPostBack then CreateDataGrid( ) end if end sub sub CreateDataGrid( ) dim dsGrid as new DataSet dsGrid = _ConfigurationSettings.GetConfig( _
"system.web/DataSetSectionHandler")
dg.DataSource=dsGrid.Tables(0) dg.DataBind( ) end sub </script> <html> <body> <form runat="server"> <h1>Configuration</h1> <asp:DataGrid id="dg" runat="server"/> </form> </body> </html>
The page in Example 20-24 first imports two namespaces necessary for working with the SQL Server database. The interesting work is done in the CreateDataGrid method. There, rather than supply a DSN and SQL query string, a call is made to the GetConfig method of the ConfigurationSettings class, which returns a DataSet object directly. Then the DataSet object is set as the DataSource of the DataGrid control, and the control is data bound. The parameter of the GetConfig method is a string containing the name of the section containing the configuration settings. Notice the syntax with the section name (system.web) separated from the subsection name (DataSetSectionHandler) by a slash.
18.116.60.158