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


 


Comments (4)
  1. adhalejr says:

    I find it significantly simpler to keep Web.{environment}.config files in my version control repository. The build process / scripts that are used to build for each environment are parameterized on the environment (e.g. "buildall qa"). So I have Web.dev.config, Web.qa.config, and Web.prod.config in version control; and the appropriate one is used when that environment is the target of a build / stage process.

  2. I’ve tried a technique similar to this before. But our group is geographically dispersed, so the development settings may vary per developer. It was a lot easier to take advantage of the file attribute on the appSettings element. It’s not an original idea but I wrote about it last week at http://www.precariousbalance.com/blogs/archive/2006/05/05/DeveloperAppSettings.aspx

  3. Ed says:

    I believe both options are pretty good combined. For the developers working on a black box you use the file path attribute and point it to a local user.config file with the settings in it, then have the zz.Test.config and zz.Production.config files with those values in it in the SC repository.  It works well, may want to plan for more than just a live environment though and extend the islive method.  Namely this allows you to just deviate the local black box development settings while preserving the production, test and other environment settings.

Comments are closed.

Skip to main content