I am not a member of any organized party.  I’m a Democrat.
Will Rogers

Taxes, are the dues that we pay for the privileges of membership in an organized society.
Franklin D. Roosevelt

Journalism is organized gossip.
Edward Eggleston

Tyranny is always better organized than freedom.
Charles Peguy

Science is nothing, but trained and organized common sense.
Thomas Henry Huxley

In windows applications or web sites, a configuration file is available (app.config or web.config). app.config becomes MyApplication.exe.config in the bin directory of a Windows application. Either file has a section for AppSettings. In this section key/value pairs can be used.

<appSettings>
 <add key="SomeKey" value="Some Value"/>
 <add key="AnotherKey" value="Another Value"/>
</appSettings>

This allows for simple configuration but is not well suited for complex or structured configuration information. This article will show how to use the interface IConfigurationSectionHandler to handle any program configuration needs.

The example shown below uses a web site and a web.config file. This technique works just as well on app.config for Windows applications.  In the web.config file, add a configSections node as the first node below configuration. Notice the sectionGroup name and section name. These define what section will be handled by this IConfigurationSectionHandler. The type attribute defines the class name that implements IConfigurationSectionHandler followed by the assembly name.

<configuration>
  <configSections>
    <sectionGroup name="Demo">
      <section name="Config" type="Data.Config.WebConfigReader,Data.Config"/>
    </sectionGroup>
  </configSections>
<configuration>

The section to read by the IConfigurationSectionHandler is shown below. Notice that localhost(Highlighted Below) is purposely spelled wrong. This misspelling shows how defaults can be used. This configuration has a list of Host Configurations and a list of known hosts. For unknown hosts, the DEV host Configuration will be used. In each Host Configuration, there is a list of email addresses to send any unhandled exceptions.

<Demo>
  <Config DefaultHostConfigurationName="DEV">
    <HostConfigurations>
      <HostConfiguration Name="DEV">
        <OnExceptionEmailList>
          <EmailAddress>John.DeveloperØyourdomain.com</EmailAddress>
          <EmailAddress>Pat.DeveloperØyourdomain.com</EmailAddress>
          <EmailAddress>Mary.TeamLeadØyourdomain.com</EmailAddress>
        </OnExceptionEmailList>
      </HostConfiguration>
      <HostConfiguration Name="TEST">
        <OnExceptionEmailList>
          <EmailAddress>John.DeveloperØyourdomain.com</EmailAddress>
          <EmailAddress>Test.Help.DeskØyourdomain.com</EmailAddress>
        </OnExceptionEmailList>
      </HostConfiguration>
      <HostConfiguration Name="PROD">
        <OnExceptionEmailList>
          <EmailAddress>AdminsØyourdomain.com</EmailAddress>
          <EmailAddress>Help.DeskØyourdomain.com</EmailAddress>
        </OnExceptionEmailList>
      </HostConfiguration>
      <HostConfiguration Name="EXPO-2008">
        <OnExceptionEmailList>
          <EmailAddress>Expo.RoadiesØyourdomain.com</EmailAddress>
        </OnExceptionEmailList>
      </HostConfiguration>
    </HostConfigurations>
    <Hosts>
      <Host Name="localhostX" HostConfigurationName="TEST"></Host>
      <Host Name="nathan.yourdomain.com" HostConfigurationName="TEST"></Host>
      <Host Name="mohinder.yourdomain.com" HostConfigurationName="TEST"></Host>
      <Host Name="peter.yourdomain.com" HostConfigurationName="DEV"></Host>
      <Host Name="claire.yourdomain.com" HostConfigurationName="DEV"></Host>
      <Host Name="hiro.yourdomain.com" HostConfigurationName="PROD"></Host>
      <Host Name="ando.yourdomain.com" HostConfigurationName="PROD"></Host>
      <Host Name="niki.yourdomain.com" HostConfigurationName="EXPO-2008"></Host>
      <Host Name="jessica.yourdomain.com" HostConfigurationName="EXPO-2008"></Host>
      <Host Name="micah.yourdomain.com" HostConfiguration="EXPO-2008"></Host>
      <Host Name="dl.yourdomain.com" HostConfigurationName="EXPO-2008"></Host>
    </Hosts>
  </Config>
</Demo>

The web page shows the information for the localhost server. Since localhostX is a misspelling, the DEV configuration will be used. If the name is changed to localhost in the web.config file, the TEST configuration will be used. Notice in the Tools class, the static demo property is read using Lazy Loading techniques.

Web Page Output

Site Host Name : localhost
Host Configuration Name = DEV
  HostType Email = John.DeveloperØyourdomain.com
  HostType Email = Pat.DeveloperØyourdomain.com
  HostType Email = Mary.TeamLeadØyourdomain.com

Source Code

protected void Page_Load(object sender, EventArgs e)
{
  Response.Write("Site Host Name : " + Tools.Demo.SiteHostName + "<br />");
  Response.Write("Host Configuration Name = " + Tools.Demo.SiteHostCofiguration.Name + "<br />");
  foreach (string email in Tools.Demo.SiteHostCofiguration.ExceptionEmailList)
  {
    Response.Write("&nbsp;&nbsp;HostType Email = " + email + "<br />");
  }
}

public static class Tools
{
  private static DemoSettings _Demo = null;
  public static DemoSettings Demo
  {
    get
    {
      if (_Demo == null)
        _Demo = (DemoSettings)ConfigurationManager.GetSection("Demo/Config");

      return _Demo;
    }
  }
}

The method ConfigurationManager.GetSection is where the configuration code is executed. The code below shows the over view of the two classes. An instance of DemoSettings will be filled when the method Create is executed.

#region Implement IConfigurationSectionHandler interface

public object Create(object parent, object configContext, XmlNode section)
{
  DemoSettings demo = new DemoSettings(ReadSimpleNode(section.Attributes["DefaultHostConfigurationName"]));

  PopulateHostConfigurationList(demo, section.SelectNodes("HostConfigurations/HostConfiguration"));
  PopulateHostList(demo, section.SelectNodes("Hosts/Host"));

  return demo;
}

#endregion

But it does not end here. Over time, configuration files evolve. More items are added. Using an IConfigurationSectionHandler allows changes to be easily incorporated. The Host Configurations shown above do not contain a database connection string. An oversight that is easily remedied. Below is one of the Host Configurations with a connection string added. To implement the change, a new property was added to the HostConfiguration class and one line was added to the Populate method(highlighted).

<HostConfiguration Name="DEV">
  <MySqlConnection>Data Source=dev;Database=dev;User ID=dev;Password=pw;</MySqlConnection>
  <OnExceptionEmailList>
    <EmailAddress>John.DeveloperØyourdomain.com</EmailAddress>
    <EmailAddress>Pat.DeveloperØyourdomain.com</EmailAddress>
    <EmailAddress>Mary.TeamLeadØyourdomain.com</EmailAddress>
  </OnExceptionEmailList>
</HostConfiguration>
private void PopulateHostConfigurationList(DemoSettings demo, XmlNodeList hostConfigurationNodeList)
{
  if (hostConfigurationNodeList != null)
  {
    foreach (XmlNode itemConfig in hostConfigurationNodeList)
    {
      DemoSettings.HostConfiguration hostConfig = new DemoSettings.HostConfiguration(ReadSimpleNode(itemConfig.Attributes["Name"]));
      hostConfig.MySqlConnectionString = ReadInnerText(itemConfig.SelectSingleNode("MySqlConnection"));
      XmlNodeList emailAddressList = itemConfig.SelectNodes("OnExceptionEmailList/EmailAddress");
      if (emailAddressList != null)
      {
        foreach (XmlNode itemEmail in emailAddressList)
        {
          string innerText = ReadInnerText(itemEmail);
          if (innerText != string.Empty)
            hostConfig.ExceptionEmailList.Add(innerText);
        }
      }
      demo.HostConfigurationList.Add(hostConfig);
    }
  }
}

Download Web Site Source Code

Ø

Tags: ,

Leave a Reply


*