RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


ASP.NET Configuration and Group Policy, Part 1: Creating and Using Custom Configuration Sections  : Page 2

This three-article series shows how to create and use custom configuration sections in ASP.NET application configuration files, and how to set Windows Group Policy at both the machine and domain level to control configuration settings from a central location.

Defining and Handling Custom Configuration Sections
You add a custom configuration section to a Web.config file by:

  • Specifying the class or assembly that implements the handler for the section in the section of Web.config
  • Inserting the matching configuration section and values into the body of the Web.config file
For example, to specify that the handler for the configuration section <CustomConnections> is the class named ConnectionSettingsSection in the CustomConfigSection namespace, and is implemented within the assembly named CustomConfigSection.dll, you would use:

     <section name="CustomConnections"
       CustomConfigSection, Version=, Culture=neutral,
This is the full syntax, and—if required—you can omit the version, culture, and public key values. And, if the class is in the App_Code folder of your web application, you also omit the assembly name, for example:

     <section name="CustomConnections"
Author's Note: For a full description of the <section> element syntax, see http://msdn2.microsoft.com/en-us/library/ms228245.aspx. Note that the type attribute value must be on a single line.

Then you can declare your custom configuration settings in the main body of Web.config using a hierarchy that corresponds to that defined within the section handler. For example:

   <CustomConnections autoConnect="true">
     <ConnectionItems deviceMode="Static">
       <add connectionType="InternalPrice" price="2"/>
       <add connectionType="ExternalPrice" price="5"/>
       <add connectionType="WirelessPrice" price="8"/>
       <add connectionType="GPRSPrice"     price="15"/>
     <defaultUser userName="John Smith" location="Block 7"/>
The next section describes the custom handler for this configuration section, as used in the example application for this article.

An Example of a Custom Configuration Section
This section describes the handler for the custom configuration section shown at the end of the previous section. The handler consists of:

  • A class named ConnectionSettingsSection that inherits from the .NET ConfigurationSection class. This class exposes:
    • The autoConnect attribute value
    • The collection of <add> elements as an instance of the custom class named ConnectionItemElementCollection
    • The <defaultUser> element as an instance of the custom class named DefaultUserElement
  • A class named ConnectionItemElementCollection that inherits from the .NET ConfigurationElementCollection class. This class exposes the deviceMode attribute value, and overrides the CreateNewElement and GetElementkey methods of the ConfigurationElementCollection base class.
  • A class named ConnectionItemElement that inherits from the .NET ConfigurationElement class. This class exposes the connectionType and price attribute for an <add> element within the parent <ConnectionItems> element.
  • A class named DefaultUserElement that inherits from the .NET ConfigurationElement class. This class exposes the userName and location attribute values from the <defaultUser> element.
If you look back at the contents of the custom section in Web.config (at the end of the previous section of this article), you'll see how this set of classes corresponds to the hierarchy of the configuration section required for the application.

The ConnectionSettingsSection Class
The ConnectionSettingsSection class corresponds to and exposes the contents of the <Connections> element that is the root of the custom configuration section. It is also the class specified in the <configSections> element that defines the handler for this section. The following code shows this class, along with the statements to reference the required .NET code namespaces and the declaration of the namespace for this and the other configuration handler classes:

   using System;
   using System.Configuration;
   namespace CustomConfigSection
     // maps to and exposes the <Connections> element  
     public class ConnectionSettingsSection : ConfigurationSection
       [ConfigurationProperty("autoConnect", DefaultValue=false,
       // returns the value of the optional "autoConnect" 
       // attribute  
       public Boolean AutoConnect
         get { return (Boolean)this["autoConnect"]; }
       // returns the <ConnectionItems> element  
       public ConnectionItemElementCollection ConnectionItems
           return (ConnectionItemElementCollection)
       // returns the <defaultUser> element
       public DefaultUserElement DefaultUser
           return (DefaultUserElement)this["defaultUser"];
Notice that the class uses [ConfigurationProperty] attributes on each public property to indicate to the .NET configuration system the corresponding values it can expect to find in the configuration. For example, the AutoConnect property carries the attribute:

      DefaultValue=false, IsRequired=false)]
This [ConfigurationProperty] declaration indicates the name of the attribute (or element) in the configuration file, specifies that the attribute is optional, and that the default value if it is not present is false. If you omit the IsRequired and DefaultValue settings, the configuration file must contain the attribute or element.

In VB.NET, the equivalent syntax is:

   <ConfigurationProperty("autoConnect", _
      DefaultValue:=False, IsRequired:=False)> _ 
Author's Note: In VB.NET you must use the line continuation character (the underscore) after the attribute so that it prefaces the Public ReadOnly Property declaration.

The ConfigurationSection base class that the ConnectionSettingsSection custom class inherits from handles parsing the file and storing the values of each attribute and element in a collection. The class code can then access the values simply by indexing into the collection, using syntax such as:

   // in C#:
   this["autoConnect"]   // the autoConnect attribute
   this["defaultUser"]   // the defaultUser child element
   ' in Visual Basic.NET:
   Me("autoConnect")      ' the autoConnect attribute
   Me("defaultUser")      ' the defaultUser child element
Each class property exposes the content of the matching section of the configuration as a typed value or specific object type, and so the code in the property accessor must cast or convert the value obtained from the configuration file to the appropriate type. This means that, if the configuration value is invalid (for example, an Int32 setting that contains a non-numeric string), the configuration class will raise an exception when the application attempts to load the configuration.

Author's Note: You can also control settings by applying validator attributes to the properties that expose the configuration values, as you'll see later in this article with the ConnectionItemElement class.

The ConnectionItemElementCollection Class
The ConnectionSettingsSection class you have just seen exposes the ConnectionItems property, which is a reference to the child <ConnectionItems> element in the custom configuration section. The custom class ConnectionItemElementCollection manages the contents of this element, as you can see in the code below. The class also exposes the value of the deviceMode attribute through the DeviceMode property:

   // maps to and exposes the <ConnectionsItems> element  
   public class ConnectionItemElementCollection 
      : ConfigurationElementCollection
      // returns the value of the optional "deviceMode" attribute  
      public String DeviceMode
            return this["deviceMode"].ToString(); 
      // override the CreateNewElement method to create 
      // a concrete instance of the collection-specific 
      // ConnectionItemElement class 
      protected override ConfigurationElement CreateNewElement()
         return new ConnectionItemElement();
      // override the GetElementKey method to return the 
      // key that identifies the element in the keyed list 
      // so that the element can be retrieved 
      protected override object GetElementKey(
         ConfigurationElement element)
         ConnectionItemElement e = (ConnectionItemElement)element;
         return e.ConnectionType;
When inheriting from the ConfigurationElementCollection class, your code must override the two methods CreateNewElement and GetElementKey. In the CreateNewElement override, you simply return a new instance of the class that represents each of the <add> elements in your custom configuration section. In this example, the <add> element is of type ConnectionItemElement.

In the GetElementKey override, you must return the value from the child <add> element's attributes that represents the key for this collection of <add> elements. This is how the configuration system will locate a specific child element. In this example, application code will query the collection for a specific <add> element by specifying a value for the connectionType attribute (such as InternalPrice) to obtain the price for this connection type. Therefore, the method override in this example casts the ConfigurationElement instance passed to it into an instance of the ConnectionItemElement type, and returns the value of this element's ConnectionType property.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date