Using multiple config files in one application

I'm supporting an ASP (Application Service Provider) style application for my company.  Instead of putting each client's settings into a single config file, I wanted to have the main config file point to each clients configuration.  After a bit of digging, I came up with a solution that works.  I don't know if it is the best solution but it does work.  My main config file now looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="FeedProvider"
                 type="Sol3.Feed.Provider.FeedProviderConfiguration, Sol3.Feed.Provider"
                 allowDefinition="MachineToApplication" />
    </configSections>
    <FeedProvider defaultProvider="FeedProvider01">
        <providers>
            <add name="FeedProvider01"
                 type="Sol3.Feed.FeedProvider01, Sol3.Feed"
                 connectionStringName="ConnString"
                 description="Client 01 Feed Provider" />
            <add name="FeedProvider02"
                 type="Sol3.Feed.FeedProvider02, Sol3.Feed"
                 connectionStringName="connString"
                 description="Client 02 Feed Provider" />
        </providers>
    </FeedProvider>
    <appSettings>
        <add key="EnvironmentName" value="dev"/>
        <!-- add key="EnvironmentName" value="qa"/ -->
        <!-- add key="EnvironmentName" value="uat"/ -->
        <!-- add key="EnvironmentName" value="prod"/ -->
        <add key="Clients" value="3"/>
        <add key="Client 1" value="Client Name 01"/>
        <add key="Client 2" value="Client Name 02"/>
        <add key="Client 3" value="Client Name 03"/>
    </appSettings>
</configuration>
A client config file now looks like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <clear />
        <add name="connString" connectionString="[client connection string]" />
    </connectionStrings>

    <appSettings>
        <add key="WatchPath" value="C:\Feeds\ClientN"/>
        <add key="FileName" value="sample.csv"/>
        <add key="FileType" value="*.csv;*.txt"/>
        <add key="StartTime" value="05:00"/>
        <add key="EndTime" value="05:00"/>
        <add key="ArchiveDays" value="30"/>
    </appSettings>
</configuration>
I have a service that will iterate through the appSettings and setup a file handler for each client.  The service creates a new ClientInfo object for each client:
        #region Constructor
        public Service()
        {
            _clientInfo = new Dictionary<string, ClientInfo>();
            _clientList = new List<string>();

            _clientCount = Convert.ToInt32(ConfigurationManager.AppSettings.Get("Clients").ToString());
            _environmentName = ConfigurationManager.AppSettings.Get("EnvironmentName").ToString();
            for (int i = 0; i < _clientCount; i++)
            {
                string appKey = String.Format("Client {0}", i+1);
                string clientName = ConfigurationManager.AppSettings.Get(appKey).ToString();
                ClientInfo thisInfo = new ClientInfo(clientName, _environmentName);
                _clientList.Add(clientName);
                _clientInfo.Add(clientName, thisInfo);
            }
        }
        #endregion


This is the ClientInfo Class and contains the code to read from another config file:
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using ITMS.Feed;
using System.IO;
using System.Diagnostics;

namespace TestHarness
{
    public class ClientInfo
    {
        #region Declarations
        private Dictionary<string, object> _config;
        private Handler _handler;
        #endregion

        #region Constructor
        public ClientInfo(string clientName, string environmentName)
        {
            clientName = clientName.Replace(" ", "_");
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = String.Format("{0}_{1}.config", clientName, environmentName);  // relative path names possible

            if (!File.Exists(Environment.CurrentDirectory + "\\" + fileMap.ExeConfigFilename))
            {
                EventLog.WriteEntry("TestHarness.ClientInfo"
                    , String.Format("{0} was not found!", fileMap.ExeConfigFilename)
                    , EventLogEntryType.Information);
                return;
            }

            // Open another config file
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            // Get the app settings section...
            AppSettingsSection section = (AppSettingsSection)config.GetSection("appSettings");

            // Get configuration settings and start file watcher for this client...
            _config = new Dictionary<string, object>();

            // read/write from it as usual
            _config.Add("connString", config.ConnectionStrings.ConnectionStrings[0].ConnectionString);
            _config.Add("WatchPath", section.Settings["WatchPath"].Value.ToString());
            _config.Add("FileType", section.Settings["FileType"].Value.ToString());
            _config.Add("StartTime", Convert.ToDateTime(section.Settings["StartTime"].Value.ToString()));
            _config.Add("EndTime", Convert.ToDateTime(section.Settings["EndTime"].Value.ToString()));

            _handler = new Handler(_config);
            _handler.Start();
        }
        #endregion
    }
}

There is still a lot I can do to this but this is the basics of handling a config file that is not your app or web config.  Enjoy.

Cross posted from my blog at http://schema.sol3.net/kbarrows

2 Comments

  • Could you please either upload the snippet of code on a download link or somehow display the entire code as some of it is hidden at the end of the lines? It would be a great help!

  • Enigman0110, Simply select the text in your browser, copy, paste into editor.

Comments have been disabled for this content.