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