现在的位置: 首页 > 综合 > 正文

Creating Custom Configuration Sections in Web.config Using .NET 2.0′s Configuration API

2013年05月15日 ⁄ 综合 ⁄ 共 11617字 ⁄ 字号 评论关闭

Ref: http://aspnet.4guysfromrolla.com/demos/printPage.aspx?path=/articles/032807-1.aspx

Introduction
Most ASP.NET applications include a number of configuration settings, such as connection strings, mail server settings, system-wide default settings, and so forth. While these settings could be hard-coded in the source code, it's usually a wiser idea to place them in a configuration file, such as Web.config. The reasoning being that if these values need to be modified, editing a configuration file is a lot easier than updating the code, rebuilding, and re-deploying.

We can define custom configuration sections in Web.config that conforms to a pre-determined XML schema. For example, our web application might have a couple of scalar configuration settings (quoteOfTheDay and yourAge) as well as a collection of settings (favoriteStates) where each setting in the collection can have its own scalar values (name and abbreviation, let's say). This configuration information could be expressed in Web.config using the following XML markup:

<ScottsSettings
     quoteOfTheDay="Hello, World!"
     yourAge="28">
   <favoriteStates>
      <add name="California" abbreviation="CA" />
      <add name="Missouri" abbreviation="MO" />
      <add name="Illinois" />
   </favoriteStates>
</ScottsSettings>

In Creating Custom Configuration Sections in Web.config we examined a technique for parsing the XML in custom configuration section that works in both ASP.NET 1.x and 2.0 applications. This required writing a bit of code. ASP.NET 2.0 applications, however, can utilize .NET 2.0's new configuration API, which makes creating custom configuration sections much easier. Read on to learn more!

Custom Configuration Section Basics
Custom configuration sections can be created in Web.config through the <configSections> element, specifying the name of the configuration section and the class type that is responsible for deserializing the configuration XML into a class instance. As we saw in the Creating Custom Configuration Sections in Web.config article, ASP.NET 1.x applications typically use two classes:

  • A handler class, which implements System.Configuration.IConfigurationSectionHandler. This class is responsible for loading the configuration markup from Web.config.
  • A configuration class whose set of properties represent the information captured in the custom configuration section. Along with providing the properties, this class also is responsible for deserializing the configuration XML passed to it from its corresponding handler class.

This approach works equally well with ASP.NET 2.0 applications. However, the .NET 2.0 Framework includes a new configuration API that makes creating custom configuration sections even easier. Rather than having to create two classes and write code that deserializes the XML into the configuration class, we can instead create the configuration class and decorate its properties with the ConfigurationProperty attribute. In short, the .NET 2.0 configuration API automatically deserializes the XML into an instance of the configuration class based on the attributes on the class's properties.

In this article we will focus solely on this new 2.0 technique; for more on the technique that works in both ASP.NET 1.x and ASP.NET 2.0, see Creating Custom Configuration Sections in Web.config.

Creating the Configuration Class
To use the .NET 2.0 configuration API, all we need to do is create a class that derives from the ConfigurationSection class. This class represents the root XML element of the custom configuration section in Web.config. To capture scalar data for the custom configuration section, simply add properties with scalar data types and decorate them using the ConfigurationProperty attribute.

Imagine that we wanted a configuration section that captured two scalar configuration settings: quoteOfTheDay and yourAge. We could create a configuration class with the following two properties:

public class ASPNET2Configuration : ConfigurationSection
{
[ConfigurationProperty("quoteOfTheDay", DefaultValue="It is what it is.", IsRequired=false)]
   public string QuoteOfTheDay
   {
      get
      {
         return this["quoteOfTheDay"] as string;
      }
   }
[ConfigurationProperty("yourAge", IsRequired=true)]
   public int YourAge
   {
      get
      {
         return (int) this["yourAge"];
      }
   }
}

The key parts are in bold. First, note that the class ASPNET2Configuration is derived from the ConfigurationSection class. Next, note the class's two properties: QuoteOfTheDay and YourAge, of types string and int, respectively. The ConfigurationProperty attribute decorating each property indicates that these properties are to be specified via the custom configuration XML. The ConfigurationProperty attribute can accept a number of parameters, including:

  • Name - this is the first parameter, which specifies the name of the property as encoded in the custom configuration XML in Web.config.
  • DefaultValue - the default value for the property if it is not specified in the custom configuration XML.
  • IsRequired - a Boolean value that indicates whether the property must be specified in the custom configuration XML. If IsRequired is true, but the property's value isn't specified in the custom configuration section in Web.config, then an exception will be thrown when attempting to visit the site.

The scalar values specified in the configuration XML can be accessed from the ConfigurationSection class using this["XmlAttributeName"], and this is the syntax used in the get accessors to read the configuration information. The configuration information cannot be directly written to (hence the omission of a set accessor).

Adding the Custom Configuration Section in Web.config
Defining the custom configuration section in Web.config for an application that uses the .NET 2.0 configuration API is no different than when using the ASP.NET 1.x approach examined in Creating Custom Configuration Sections in Web.config. To use the custom configuration section in Web.config, we need to first define it in the element like so:

<configuration>
  
  <!-- Define the custom configuration sections... -->
  <configSections>
    <section name="aspnet2ConfigurationDemo" type="ASPNET2Configuration"/>
  </configSections>
  
  <system.web>
     ...
  </system.web>
</configuration>

Note that the type value is the fully-typed name of the configuration class. Since the handler class appears in my App_Code folder, the value for the type attribute is simply the class's name (ASPNET2Configuration). If this class resided in a separate assembly, the type value would be: "Namespace.ClassName, AssemblyName".

With the custom configuration section specified in <configSections>, we can add the custom section to Web.config. Note that the custom section, like <configSections>, appears outside of the <system.web> section:

<configuration>
  
  <!-- Define the custom configuration sections... -->
  <configSections>
    <section name="aspnet2ConfigurationDemo" type="ASPNET2Configuration"/>
  </configSections>
  
  <aspnet2ConfigurationDemo 
        quoteOfTheDay="Love your enemy like thy neighbor." 
        yourAge="28" />
  
  <system.web>
     ...
  </system.web>
</configuration>

Since the yourAge property was marked as IsRequired=true, if the value is omitted a configuration error is displayed when attempting to visit the site with the message: "Required attribute 'yourAge' not found."

Omitting yourAge results in a configuration error.

Programmatically Accessing the Configuration Information
To work with the configuration information from an ASP.NET page or one of the classes that make up the application's architecture, we need to use the ConfigurationSettings class's GetConfig method, passing in the path to the markup we are interested in ("aspnet2ConfigurationDemo", for this example). This can be accomplished using the following code snippet:

ASPNET2Configuration configInfo = (ASPNET2Configuration) ConfigurationSettings.GetConfig("aspnet2ConfigurationDemo");
// Work with the properties from the ASPNET2Configuration class...
string quote = configInfo.QuoteOfTheDay;
...

What's cool about the GetConfig() method is that is automatically caches the configuration information. This data remains cached until the application is restarted (such as through restarting the webserver, modifying Web.config, uploading an assembly to the /bin folder, and so on).

Rather than having to enter the above code each time we want to work with configuration data, we can add a static method to the ASPNET2Configuration that encapsulates this logic.

public static ASPNET2Configuration GetConfig()
{
   return ConfigurationSettings.GetConfig("aspnet2ConfigurationDemo") as ASPNET2Configuration;
}

With this method in place, accessing a configuration value is as easy as doing the following:

string quote = ASPNET2Configuration.GetConfig().QuoteOfTheDay;

Capturing Collection-Based Configuration Information
The code we've examined thus far has only allowed for scalar properties defined as attributes in the configuration markup. But what if we want to capture a set of values? Imagine that for our application we want to display information about a number of states (or cities or countries), but want to let the page developer dictate what states, exactly, are available from the application. In short, we want to augment the custom configuration markup to include a collection. To accomplish this using .NET 2.0's configuration API we need to create two new classes: one that models the data that represents each instance of the collection and one that models the collection.

For example, imagine that we wanted to capture the name and abbreviation of a variable number of states via the custom configuration section. We would start by creating a class that derives from the ConfigurationElement class and captures information for a particular state (namely its name and abbreviation). Just like with the ASPNET2Configuration, these scalar values are specified via class properties using the ConfigurationProperty attribute:

public class ASPNET2ConfigurationState : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired=true)]
   public string Name
   {
      get
      {
         return this["name"] as string;
      }
   }
[ConfigurationProperty("abbreviation", IsRequired=false)]    public string Abbreviation
   {
      get
      {
         return this["abbreviation"] as string;
      }
   }
}

Next we need to create a class that models a collection of ASPNET2ConfigurationState objects. The .NET 2.0 configuration API includes a ConfigurationElementCollection base class that we can extend to capture a set of ASPNET2ConfigurationState objects. When extending the ConfigurationElementCollection class we need to override the CreateNewElement and GetElementKey methods. These CreateNewElement method is responsible for creating a new instance of the object being held by the collection. Each object in the collection is indexed via a key, so we need to specify what property of the objects in the collection qualifies as the key. The GetElementKey returns the key value for a particular element in the collection.

public class ASPNET2ConfigurationStateCollection : ConfigurationElementCollection
{
   public ASPNET2ConfigurationState this[int index]
   {
      get
      {
         return base.BaseGet(index) as ASPNET2ConfigurationState;
      }
      set
      {
         if (base.BaseGet(index) != null)
         {
            base.BaseRemoveAt(index);
         }
         this.BaseAdd(index, value);
      }
   }
   protected override ConfigurationElement CreateNewElement()
   {
      return new ASPNET2ConfigurationState();
   }
   protected override object GetElementKey(ConfigurationElement element)
   {
      return ((ASPNET2ConfigurationState)element).Name;
   }

}

Now that the two necessary classes have been created, we can add the collection class (ASPNET2ConfigurationStateCollection) as a property of the ASPNET2Configuration class:

public class ASPNET2Configuration : ConfigurationSection
{
   ... QuoteOfTheDay and YourAge properties and GetConfig() method removed for brevity ...
[ConfigurationProperty("favoriteStates")]
   public ASPNET2ConfigurationStateCollection FavoriteStates
   {
      get
      {
         return this["favoriteStates"] as ASPNET2ConfigurationStateCollection;
      }
   }

}

A Simple Demo
The download at the end of this article includes the custom configuration classes examined in this article along with a simple demo illustrating how to read the configuration data from code in an ASP.NET page's code-behind class. The demo includes a Label Web control that displays the various configuration setting values. For example, given the following configuration settings:

<aspnet2ConfigurationDemo
        quoteOfTheDay="Love your enemy like thy neighbor."
        yourAge="28">
  <favoriteStates>
    <add name="California" abbreviation="CA"/>
    <add name="Missouri" abbreviation="MO"/>
    <add name="Illinois" />
  </favoriteStates>
</aspnet2ConfigurationDemo>

The demo displays the following output:

Be sure to download the demo and code at the end of this article and give it a try on your computer.

Conclusion
In this article we explored the .NET 2.0 configuration API and how it can be used to specify custom configuration settings in Web.config. Unlike the approach used in ASP.NET 1.x, the custom configuration API automatically handles the deserialization of configuration markup to our configuration classes.

Happy Programming!

  • By Scott Mitchell
  • 抱歉!评论已关闭.