Trevor Power

22 October 2009

Sharing configuration settings in Visual Studio

Correctly managing your systems settings during both development and deployment can save you a lot of time. When ever you have to manually change settings there is the opportunity to mess up, so I try to automate any repetitive configuration tasks. It often happens that application settings or connection strings are needed by more than one component in your system. The solution I use is a variation of this method of sharing app.config files between applications, except that it allows each project to have its own app.config or web.config files which reference the common settings.

Creating shared settings

The first step is to make a settings class that acts as a wrapper around the values in the configuration files. This is a very simple class inheriting ApplicationSettingsBase and looks like this:
using System.Configuration;

namespace TP.Example.Configuration
{
    public class Settings : ApplicationSettingsBase
    {
        private static Settings _defaultInstance =
                (Settings)(ApplicationSettingsBase.Synchronized(new Settings()));

        public static Settings Default { get { return _defaultInstance; } }

        [ApplicationScopedSettingAttribute()]
        string ServiceName
        {
            get { return ((string)(this["ServiceName"])); }
            set { this["ServiceName"] = value; }
        }

        [ApplicationScopedSettingAttribute()]
        string EventLogName
        {
            get { return ((string)(this["EventLogName"])); }
            set { this["EventLogName"] = value; }
        }

        [ApplicationScopedSettingAttribute()]
        [SpecialSettingAttribute(SpecialSetting.ConnectionString)]
        string ConnectionString
        {
            get { return ((string)(this["ConnectionString"])); }
            set { this["ConnectionString"] = value; }
        }
    }
}
The next step is to create the files that contain the settings. I usually have two, one for application settings and one for connection strings. The application settings file consists of a single node matching the full name of my settings class:
<TP.Example.Configuration.Settings>
  <setting name="ServiceName" serializeAs="String">
    <value>My Example Service
  </setting>
  <setting name="EventLogName" serializeAs="String">
    <value>ExampleLogName
  </setting>
</TP.Example.Configuration.Settings>
The connection strings file consists of one 'connectionStrings' node. Note the name of the connection string is qualified with the full name of my settings class.
<connectionStrings>
  <add name="TP.Example.Configuration.Settings.ConnectionString" connectionString="[...]" />
</connectionStrings>
These files should exist outside any of your projects but be under source control. I usually put them in a solution folder 'Configuration' that contains a simple project with the above settings class: 'Configuration' solution folder

Referencing shared settings

FilesAsLinksThese common settings are now ready to be used by any project in the solution by following these steps:
  1. Add a reference to the settings project.
  2. Add a link to settings files and turn on 'copy to output directory'
  3. Include settings files in the app.config/web.config

To link to the settings files you should Add -> Existing Item -> Add As Link, they will then appear with a shortcut icon. This means that they only point to the original file, so there is no duplication.

Now that the files are in our project we just need to get our App.config file to include them. A simplified App.config would look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup" >
      <section name="TP.Example.Configuration.Settings" type="System.Configuration.ClientSettingsSection" />
    </sectionGroup>
  </configSections>
  <connectionStrings configSource="TP.Example.Configuration.ConnectionStrings.config" />
  <applicationSettings>
    <TP.Example.Configuration.Settings configSource="TP.Example.Configuration.AppSettings.config" />
  </applicationSettings>
</configuration>

Now when you modify one of these files the change will be picked up by all other projects in the solution.

Websites and Web.config

Using these settings in a website requires one extra step. As before, the settings file will be linked to by the project file and the 'Copy to Output Directory' turned on. The problem is that the web.config file is usually at the root while the output directory is 'bin' or 'bin/Debug' depending on your setup. Because the output folder can depend on the build configuration, I have found the best solution is to copy the config files from the target directory to the project directory. This is just one line in the build events.COPY $(TargetDir)*.config $(ProjectDir) Writing it out like this sounds like a lot of work but it is easy to setup and easy to maintain. If you have any question or have a better solution, please leave a comment.

This post has been closed for commenting, but you can still contact me directly.