Creating custom web.config sections

January 28, 2009

I have resisted making full use of ASP.NET 2.0’s Configuration API for the longest time. On many occasion it has occurred to me that it might make sense to create a custom configuration section in the web.config for whatever reason, but I then quickly followed my two-step decision process:

  1. Google “creating custom web.config sections” and see a bunch of examples, all of which seem to require more than 10 lines of code.
  2. Decide it would be easier to make a number of appSettings entries instead.

The reality is, if you can satisfy your needs by using the built-in appSettings, you probably have no business taking the time to create your own config section.  While you could create your own to represent a similar keys & values section, the need for a custom web.config section really arises when you have multiple properties, a dynamic amount of entries, some sort of hierarchal data structure, or any combination of.

4 Guys From Rolla has a great walkthrough which I used for my basis of learning. Yes, unfortunately it does require a fair amount of code, but it is reasonably straightforward. Below is my mini-tutorial, and at the end of this post there’s a live demo and source-code download.

You will first need to create a class which inherits ConfigurationSection, which represents the root XML element of your custom config section.  You can add scalar-value properties to this class using the ConfigurationPropertyAttribute class.

We’re also going to add a static GetConfig() method which will return the configuration section, saving a bit of code later down the road.

public class ContactSection : ConfigurationSection
{
    public static ContactSection GetConfig()
    {
        return ConfigurationManager.GetSection("customConfig/contactSection") as ContactSection;
    }

    [ConfigurationProperty("Locations")]
    public LocationCollection Locations
    {
        get { return this["Locations"] as LocationCollection; }
    }

    [ConfigurationProperty("name", IsRequired = true)]
    public string Name
    {
        get
        {
            return (string)this["name"];
        }
    }
}

Below is my configSections from the web.config. Note that “customConfig/contactSection” in line 5 above maps to my section group and section.

<configSections>
    <sectionGroup name="customConfig">
        <section name="contactSection" type="ContactSection"/>
    </sectionGroup>
</configSections>

We have two more classes to complete to represent the “Location” and “LocationCollection” on line 8 of the ContactSection class, which will allow us to have a collection of entries in the web.config. These classes inherit ConfigurationElement and ConfigurationElementCollection classes, respectively. Here’s an example:

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

    [ConfigurationProperty("address", IsRequired = false)]
    public string Address { get { return this["address"] as string; } }

    //City, State, and Zip properties removed for brevity
}


public class LocationCollection : ConfigurationElementCollection
{
    public Location this[int index]
    {
        get { return base.BaseGet(index) as Location; }
        set
        {
            if (base.BaseGet(index) != null)
                base.BaseRemoveAt(index);
            this.BaseAdd(index, value);
        }
    }

    // to get by key value instead of index
    public Location this[string key]
    {
        get { return base.BaseGet(key) as Location; }
    }


    protected override ConfigurationElement CreateNewElement()
    {
        return new Location();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((Location)element).Name;
    }
}

The contactSection in the web.config then looks like this:

<contactSection name="Joe the Plumber" phone="123-456-7890">
    <Locations>
        <add name="Primary" address="123 street" city="Columbus" 
            state="OH" zip="99999"></add>
        <add name="Vacation Home" zip="90210"></add>
    </Locations>
</contactSection>

That’s everything needed to implement your custom configuration section with attributes and a collection of elements. All that’s left to do is actually reference our configuration section in code:

protected void Page_Load(object sender, EventArgs e)
{
    Response.Write("Name: " + ContactSection.GetConfig().Name);
    Response.Write("<br/>Locations:<br/>");
    foreach (Location l in ContactSection.GetConfig().Locations)
    {
        Response.Write("<b>" + l.Name + "</b> - ");

        //if optional properties are omitted in config, 
        //they are a blank string here
        if (l.Address != "")
            Response.Write(" Address: " + l.Address);
        if (l.City != "")
            Response.Write(" City: " + l.City);
        if (l.State != "")
            Response.Write(" State: " + l.State);
        if (l.Zip != "")
            Response.Write(" Zip: " + l.Zip);

        Response.Write("<br/>");
    }
}
blog comments powered by Disqus

About me

I'm a consultant with Headspring in Austin, TX. My passion is creating web-based applications that are well crafted and solve real problems for real people. Want to know more? Check out my about page.

WTF is all this code? I came here for food!

My wife made a new year's resolution to try out at least one new recipe each week. Want to know what she's been feeding me? resolutionfood.blogspot.com