Custom .NET Configuration Settings: Part 1

If you’ve worked much with storing and retrieving configuration data in your .NET application’s app.config or web.config file, you’ve probably run across the AppSetting property on the System.Configuration.ConfigurationManager class.  This property allows you to retrieve any custom name/value pairs that you might need for your application, as shown below:

string smtpHost = System.Configuration.ConfigurationMananger.AppSettings["smtpHost"];
int pageSize = (int)System.Configuration.ConfigurationMananger.AppSettings["pageSize"];

In your application’s app.config or web.config file, you store your custom settings as follows:

<appSettings>
  <add key="smtpHost" value="smtp.gmail.com"/>
  <add key="pageSize" value="10"/>
</appSettings>

This is the fastest and easiest way to store and retrieve custom configuration settings for your application. However, there are a few downsides:

  • You have to access each custom setting using a string indexer, which is prone to errors that the compiler can’t catch if you mis-key a setting name.  Ugh.
  • Every setting is returned as a string.  So, if you’re storing a setting for something that is not a string type (like page size in this example), you’ll need to cast the returned value.  Kinda messy.
  • If you need to store settings that have a structure more complicated that just name/value pairs, the AppSettings property can’t help you. Boo.

To help with these issues, the .NET Framework provides the System.Configuration.ConfigurationSection class, which provides the plumbing you need to wrap a class around a section of a configuration file.  From our previous example, we can derive a class from System.Configuration.ConfigurationSection:

using System;
using System.Collections.Generic;
using System.Configuration;

namespace MyApp
{
    public class MyAppConfiguration : ConfigurationSection
    {
        [ConfigurationProperty("smtpHost", IsRequired = true)]
        public string SMTPHost
        {
            get { return (string)this["smtpHost"]; }
        }

        [ConfigurationProperty("pageSize", IsRequired = true)]
        public int PageSize
        {
            get { return (int)this["pageSize"]; }
        }
    }
}

In your application’s config file, rather than storing the configuration data in the AppSettings section, you can now store it in your own custom section, which is represented by the above MyAppConfiguration class.

<configuration>

    <configSections>
        <section name="myAppConfiguration" type="MyApp.MyAppConfiguration, MyApp" />
    </configSections>

    <myAppConfiguration smtpHost="smtp.gmail.com" pageSize="10" />

</configuration>

Notice the three different pieces of information stored in the configuration file, the definition of the custom section (<section>), its name (name=”myAppConfiguration”), and the class type/assembly that represents it (type=”MyApp.MyAppConfiguration, MyApp”). With these three pieces in place, you can now access your custom settings from anywhere in your application:

MyAppConfiguration myAppConfiguration = System.Configuration.ConfigurationManager.GetSection("myAppConfiguration") as MyAppConfiguration;
string smtpHost = myAppConfiguration.SMTPHost;
int pageSize = myAppConfiguration.PageSize;

This is a nice improvement over the AppSettings approach in that it gives us strongly-typed access to our configuration settings, which reduces typo errors that the compiler can’t catch and also provides us with IntelliSense support in Visual Studio. This approach also allows us to define configuration data structures that are more complicated than simple name/value pairs, although that is not demonstrated here (I’ll leave that for a future post).

We could stop here and this would definitely be a nice improvement. However, there is still some room for more improvement. For one, this approach requires us to make a call to the ConfigurationManager every time we want to access configuration data. Plus, that call requires us to use a string indexer, which again opens us up to the possibility of typos that the compiler can’t catch for us. In response to these issues, we can add some additional code to our MyAppConfiguration class.

using System;
using System.Collections.Generic;
using System.Configuration;

namespace MyApp
{
    public class MyAppConfiguration : ConfigurationSection
    {
        public static MyAppConfiguration Current
        {
            get { return (MyAppConfiguration)ConfigurationManager.GetSection("myAppConfiguration"); }
        }

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

        [ConfigurationProperty("pageSize", IsRequired = true)]
        public int PageSize
        {
            get { return (int)this["pageSize"]; }
        }
    }
}

We modified the existing MyAppConfiguration class and added a static MyAppConfiguration property called Current, making our class a “singleton”. This allows us to directly access the configuration setting we need without any setup, like this:

string smtpHost = MyAppConfiguration.Current.SMTPHost;
int pageSize = MyAppConfiguration.Current.PageSize;

Now that feels good. We can now access any custom configuration property with one line of code, and the code is strongly-type and capable of representing complex configuration structures (not shown in this example but in a future post).

I hope you found this example useful and can incorporate it into your development toolbox.

Enjoy!

Advertisements

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