Search EggHeadCafe's Job Board
EggHeadCafe Silverlight WPF ASP.NET VB.NET C# Excel SQL Server SharePoint
search
MicrosoftArticlesForumsFAQs
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml / Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

WebArticlesForumsFAQs
JavaScript
ASP
ASP.NET
WCF

DatabasesArticlesForumsFAQs
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsFAQs
Excel
Word
Powerpoint
Outlook
Publisher
Money

Non-MicrosoftArticlesForumsFAQs
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

Operating SysArticlesForumsFAQs
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsFAQs
BizTalk
Site Server
Exhange Server
IIS

Graphic DesignArticlesForumsFAQs
Macromedia Flash
Adobe PhotoShop
Expression Blend
Expression Design
Expression Web

OtherArticlesForumsFAQs
Lounge
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Product Reviews
Search Engines
Resumes

 

Some ASP.NET 2.0 Configuration Tips


By Peter Bromberg
Printer Friendly Version
View My Articles
136 Views
    

Illustrates some common techniques for managing web.config sections across multiple deployments and modes for ASP.NET 2.0 Web applications.


 It is a common scenario for ASP.NET Web developers to want to have different sets of configuration data depending on whether the project is being developed locally within Visual Studio in Debug mode, being tested in QA in Release mode, or is in Release mode in production. Also, settings may differ from machine to machine if the Application is deployed into a web farm scenario.

 There are several ways to enhance the ability to maintain separate sets of configuration data; the typical environment is one where we have a number of settings in the web.config that will rarely be changed, and some others that we do want to be able to have changes based on what mode and what location the application is being run from.

 The simplest technique, and one that is workable in a majority of scenarios, is to use the "file=" attribute of the appSettings section:

<appSettings file="myCustomAppSettings.config" >
   <add key="one" value="this will be overwritten by the same key in the external file" />
  </appSettings>

  //(myCustomAppSettings.config file:)

<appSettings>
<add key="one" value="this will replace the key in the main web.config with the same name" />
  <add key="two" value="this is from the external file" />
</appSettings>
Note that the root element of the external file is "<appSettings>". Any keys in this file with the same key name as one present in the main web.config appSettings section will overwrite the one in web.config. All others are simply added to the collection, which is a NameValueCollection. For example, the following snippet will write out these values to a Page:

NameValueCollection coll= ConfigurationManager.AppSettings;
    Response.Write("<b>appSettings Section:</b><BR/>");
     foreach(string key in coll.AllKeys)
         { 
             Response.Write(key +": "+coll[key] +"<br/>");
         }

Any settings in the web.config appSettings section that aren't replaced by the external definitions because of having the same key name will appear first in the collection.

With this arrangement, you can have a separate "myCustomAppSettings.config" file in each deployment, and when the web.config is deployed, this file is left alone. So, each deployment location can have one of these that will always contain different items without fear of copying a debug web.config into a production deployment and destroying required items and values.


Other standard sections can also be read directly from web.config with the use of an external file. For these you would use the configSource attribute:

<connectionStrings configSource="externConnectionStrings.config" />

//(externConnectionStrings.config file:)
<connectionStrings>
 <add name="conn1" connectionString="Note that the localSqlServer shows up because it is defined in web.config (machine.config) and we did not use the clear or remove directives" providerName="SqlClient" />
</connectionStrings>
Note that in this case the root element of the external file must be the name of the standard section that's being imported - in this case, "connectionStrings".
You will see that because we did not use the <clear /> or <remove name="localSqlServer" /> elements, the list that is output will include this connection string as the first  item in the ConnectionStringSettingsCollection that is output. That is because it is predefined in the master web.config file in the .NET Framework directory:


ConnectionStringSettingsCollection cnColl = ConfigurationManager.ConnectionStrings;
    foreach(ConnectionStringSettings set in cnColl)
        {
            Response.Write(set.Name + ": "+set.ConnectionString +"<br/>");
        }

Finally, you can create a custom configuration "appSettings" section of your choice using the System.Configuration.AppSettingsSection class:

In the web.config:

<configSections>
      <section name ="states" type="System.Configuration.AppSettingsSection,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> 
</configSections> <states file="states.config" > <add key="Arizona" value="AZ" /> </states> <system.web> ...
In the "states.config" external file:

<states>
<add key="New York" value ="NY" />
<add key="Massachusetts" value="MA" />
</states>
The elements are combined at runtime, with the one(s) in the web.config appearing first in the collection. Here is an example of reading the above section:

string configPath = HttpContext.Current.Request.CurrentExecutionFilePath;
  configPath = configPath.Substring(0, configPath.LastIndexOf('/'));
      if (configPath.Length == 0) configPath = "/";
         Configuration myRootConfig = WebConfigurationManager.OpenWebConfiguration(configPath);
         AppSettingsSection myAppSettings = myRootConfig.GetSection("states") as AppSettingsSection;
         KeyValueConfigurationCollection myColl = myAppSettings.Settings;
         foreach(KeyValueConfigurationElement elem in myColl)
            {
                Response.Write(elem.Key +": "+elem.Value +"<br/>");
            }

Note that with this arrangement, it is possible to have multiple web.config files at various locations on the filesystem. Provided that the correct path is supplied to the configPath variable as above, that is the web.config that will be loaded and processed.  This provides for a lot more "custom" flexibility at the expense of a bit more complicated code.

The WebConfigurationManager class in the System.Web.Configuration namespace is the main programming point that allows for custom manipulation of configuration data. It includes static methods to retrieve application settings and connection strings.  It works much like the ConfigurationManager class but is oriented toward web applications.


The GetSection static method takes an XPath expression to indicate the section you want to get, and allows you to cast the resulting object to a strongly typed reference for built-in section types.  For example, here is how one can read the <identity... section:

IdentitySection section;
 section = WebConfigurationManager.GetSection("system.web/identity") as IdentitySection;
    if (section != null)
    {
       Response.Write("Identity: Impersonate = " + section.Impersonate);
    }
The output page from the sample app should look like this:

appSettings Section:
one: this will replace the key in the main web.config with the same name
two: this is from the external file

connectionStrings Section:
LocalSqlServer: data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true
conn1: Note that the localSqlServer shows up because it is defined in web.config (machine.config) and we did not use the clear or remove directives

Custom appSettings Section (states):
Arizona: AZ
New York: NY
Massachusetts: MA

Identity Section (via GetSection):
Identity: Impersonate = True


Using the classes in the Configuration namespace, developers have all the tools needed to programmatically create, read, edit and save web.config and related configuration files. There is almost never a need to, nor would it be advisable to "roll your own", unless you are creating custom configuration files  -- all you need to do is study and learn to use the existing API.

If you want to see an advanced use of this concept, download the Enterprise Library 3.1 and look at how the custom sections and their respective classes are created and modified for the various parts of the Library.

Finally, if you create external configuration "include" files, it is a good idea to give them the ".config" extension. Files with this extension are never served by IIS under ASP.NET.  And one final tip: an easy way to get the assembly metadata string for the creation of a configSection element is to load the assembly via Reflector. The entire string will appear at the bottom of the main window when the loaded assembly is selected in the tree list, and you can copy it to the clipboard. Let me tell you, if Google is your friend for finding stuff on the web, Reflector is your friend for finding stuff in the .NET Framework.

The downloadable Visual Studio 2005 Web Application Project will illustrate all of the above.

Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites.
Please post questions at forums, not via email!

button
Article Discussion: Some ASP.NET 2.0 Configuration Tips
Peter Bromberg posted at Sunday, June 17, 2007 4:08 PM
Original Article