Keeping Your Configuration Settings Straight.

One of the challenges our group deals with is finding an easy and reliable way to get our applications from development… to stage/test… to production while keeping all the various configuration settings straight.  This is obviously not a new problem and one that has been solved by others a variety of different ways.  Our group supports and maintains a long list of internal applications and we tend to update many of those application frequently throughout a given week.  Because of this, we needed to come up with an easy way to manage the application specific configuration settings that wasn’t prone to error.

 

The problem is that we didn’t want to be changing the configuration settings of an application each time we moved it from one environment to another… The solution was a simple little wrapper around the ConfigurationSettings class that allows the application to recognize its environment and then use the appropriate configuration settings automatically.  The result is that we can now publish our applications to any environment and trust that the applications will be using the proper configuration settings.  Here’s how it works…

 

First, is the ConfigurationSettings wrapper which has two simple methods – IsRunningOnLiveServer() and GetValue():

 

public class Configuration

{

/// <summary>

/// Checks if the application is running on one of the

/// live servers listed in the .config file.

/// </summary>

/// <returns>True/False.</returns>

static public bool IsRunningOnLiveServer()

{

ArrayList servers = new ArrayList(ConfigurationSettings.AppSettings["PRODUCTION_Servers"].Split(','));

       if (servers.Contains(Environment.MachineName.ToLower()))

       {

              return true;

       }

       else

       {

              return false;

       }

}

/// <summary>

/// Gets a config value from the .config file based on whether or not the machine

/// running the code is a production or development server.

/// </summary>

/// <param name="configString"></param>

/// <returns>Config value </returns>

public static string GetValue(string configString)

{

       try

       {

              // Check if we're running on the live server.

              string thisKey

= IsRunningOnLiveServer() ? "PRODUCTION_" + configString : configString;

             

              // Check if the key exists and return the value.

              ArrayList keys = new ArrayList(ConfigurationSettings.AppSettings.AllKeys);

              if (keys.Contains(thisKey))

              {

                     return ConfigurationSettings.AppSettings[thisKey];

              }

              else

              {

                     // Return the original key.

                     return ConfigurationSettings.AppSettings[configString];

              }

       }

       catch

       {

              // If we fail returning a production configuration string

              // we'll just return the development one.

              return ConfigurationSettings.AppSettings[configString];

       }

}

}

There’s really nothing fancy about this code, but you can clearly see that its purpose is to let the application figure out which configuration setting it should use – production or development.

 

Next is the configuration file itself:

 

<appSettings>

<add key="PRODUCTION_Servers" value="PROD1,PROD2,etc."/>

       <!-- Production settings -->

       <add key="PRODUCTION_CnString" value="server=PROD_SQL1;database=MyDB... "/>

    <add key="PRODUCTION_EmailDebug" value="False" />

    <add key="PRODUCTION_SomeOtherSetting" value="False" />

   

<!-- Development settings -->

       <add key="CnString" value="server=DEV_SQL1;database=MyDB... " />

    <add key="EmailDebug" value="True" />

    <add key="SomeOtherSetting" value="True" />

</appSettings>

 

And finally, instead of calling the ConfigurationSettings class directly, our applications all call the new Configuration.GetValue method to retrieve the various configuration settings.  Example:

 

m_Db = Database(Configuration.GetValue("CnString"));

 

Again, the result of this is that we can now publish our applications to any environment without changing the configuration files and trust that everything will be configured properly.

 

There are many different ways you could modify this solution to work for you.  We chose to keep the list of production servers in the application configuration files, but you could just as easily store them in the registry on each machine, in a machine.config file, or anywhere you choose for that matter.  So, if you find yourself in a situation where you’re struggling to keep your configuration settings straight from one environment to the next you might look towards a solution similar to this one.

 

Aaron Bjork