Custom ConfigurationSections in .NET 2.0 .config Files

Recently, I was needing to store information about 5 instances of an application server that I was accessing from my program.  As I was entering the third set of values in <appSettings> section I decided to go a better route.  What I wanted seemed simple: a section that worked exactly like the <connectionStrings> section, but with my own attributes.  After several hours with the documentation and some on-line research, I got what I wanted.  I was hoping it would only take 20-30 minutes.  In order to provide you with the experience I hoped to have, I have written this post.

First, let show you what I wanted my section to look like:

<acmeConfiguration>
 <add name="ERCOT"
  connectionName="AcmeER" fileDir="\\server\path" baseUrl="http://server:9999" />
  <add name="PM"
   connectionName="AcmePM" fileDir="\\server2\path" baseUrl="http://serverxx:9901" />
</acmeConfiguration>

You will need to subclass three classes from System.Configuration namespace: ConfigurationSection, ConfigurationElementCollection, and ConfigurationElement which correspond to the <acmeConfiguration>, the set of elements within <acmeConfiguration>, and the <add> elements respectively.  Understanding the above is the key to simplifying this exercise.  Here’s the code that implements the section above:

public class AcmeConfigSection : ConfigurationSection {
[ConfigurationProperty("", IsRequired=true, IsDefaultCollection=true)]
  public AcmeInstanceCollection Instances {
   get { return (AcmeInstanceCollection) this[""]; }
   set { this[""] = value; }
  }
}

public class AcmeInstanceCollection : ConfigurationElementCollection {
  protected override ConfigurationElement CreateNewElement() {
   return new AcmeInstanceElement();
  }
  protected override object GetElementKey(ConfigurationElement element) {
   return ((AcmeInstanceElement) element).Name;
  }
}
public class AcmeInstanceElement : ConfigurationElement {
  [ConfigurationProperty("name", IsKey=true, IsRequired=true)]
  public string Name {
   get { return (string) base["name"]; }
   set { base["name"] = value; }
}

  [ConfigurationProperty("connectionName", IsRequired=true)]
  public string ConnectionName {
   get { return (string)base["connectionName"]; }
   set { base["connectionName"] = value; }
  }

  [ConfigurationProperty("fileDir", IsRequired = true)]
  public string FileDir {
   get { return (string)base["fileDir"]; }
   set { base["fileDir"] = value; }
  }

  [ConfigurationProperty("baseUrl", IsRequired = true)]
  public string BaseUrl {
   get { return (string)base["baseUrl"]; }
   set { base["baseUrl"] = value; }
  }
 }

Finally, for convenience, I created a class to provide static access to this collection similar to System.Configuration.ConfigurationManager.ConnectionStrings:

public class AcmeConfig {
  protected static Dictionary<string, AcmeInstanceElement> _instances;
  static AcmeConfig() {
   _instances = new Dictionary<string,AcmeInstanceElement>();
   AcmeConfigSection sec = (AcmeConfigSection) System.Configuration.ConfigurationManager.GetSection("AcmeConfiguration");
   foreach ( AcmeInstanceElement i in sec.Instances ) {
    _instances.Add(i.Name, i);
   }
  }
  public static AcmeInstanceElement Instances(string instanceName) {
   return _instances[instanceName];
  }

  private AcmeConfig() {
  }

}

That’s it.  I wish MS would put a sample like mine in the docs because I think this is what 99% of developers are looking for.

About these ads

14 Responses to “Custom ConfigurationSections in .NET 2.0 .config Files”

  1. Sebastian Patten Says:

    Thanks for the useful information.

    The logic they used for implementing this kind simple custom XML configuration seems a bit too complex don’t you think?

    Also whats the deal with
    this[“”]

    I also didn’t notice that i needed to make the collection items “Add” items. I at first tried to implement my own name for these nodes.

    Thanks again for the good resource – it saved me some time!

  2. Conrad Says:

    Hmm Microsoft do have a example on MSDN, but it’s written as you say in a contrived way, there are some good tips in there, but the MSDN sample it just not useable in a non-trivial application because it suffers from the “copy-paste” defect all over the place.
    Good work John

  3. Optimus Prime Says:

    Code formatting man, code formatting
    Otherwise very useful post

    • DK Says:

      Instead of using Dictionary how would you create a List. For a custom config section like this:

      <add name="ERCOT"
      <add name="PM"

  4. Andrew James Craswell Says:

    This is EXACTLY what I wanted. This has saved me hours of time at work. Thanks for the lesson :D

  5. Creating a custom section in Web.config « Anders G. Nordby Says:

    […] Today I found the need to create a custom section in Web.config. Being quite a while since last time I did this, I spent some time googling around until I found this blogpost from 2007: Custom ConfigurationSections in .NET 2.0 .config Files […]

  6. Charlie Says:

    Seems to have stripped out the xml, trying again
    <section name="serviceConfiguration" type="ConsoleApplication1.ServiceConfigSection, ConsoleApplication1"

  7. AJ Says:

    thanks, john. this really helped!

  8. Josep Maria Vidal Says:

    Thanks.

  9. Mike Says:

    Why can’t the MS examples be this simple?

    Thanks

  10. Jeremy Bunga Says:

    Thanks! Great post, really neat example, saved me a lot of time!

  11. Munawar Says:

    I’m having problem in the following line

    AcmeConfigSection sec = (AcmeConfigSection)System.Configuration.ConfigurationManager.GetSection(“acmeConfiguration”);

    The ‘sec’ object is showing up as null in runtime.

    This is the app.config I’m using.

    Also, one more question – Is there any reason why following is an empty string instead of ‘acmeConfiguration’

    public class AcmeConfigSection : ConfigurationSection
    {
    [ConfigurationProperty(“”, IsRequired = true, IsDefaultCollection = true)]
    public AcmeInstanceCollection Instances
    {
    get { return (AcmeInstanceCollection)this[“”]; }
    set { this[“”] = value; }
    }
    }

  12. Munawar Says:

    Sorry, reposting with the app.config


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: