Problem Statement

Recently I got a requirement where I have many modules and each is independent applications like some are the web application, WinForms and also we have windows services. But here we have most of the settings in common. Such as all applications pointing to the same database and also pointing to same business logic. Maintaining multiple copies of same settings gives lots of maintenance issues.

To solve this we need to have a centralized place from where all applications will pick their configuration settings. This way we will be the low risk of missing any new setting add/update in any module.

To achieve this, the following is the best approach to implement centralization of configurations.

Solution 

Our approach for this would be, will maintain a CentralApp.config file and this file will be same as our existing app.config file. This CentralApp.config will contain all the common configurations like connection strings, app settings etc..,.

When an application starts or run, all the configurations on CentralApp configuration file will be replaced with the individual app or web.config files. The other feature of this approach is if any configuration elements available in the central app and not available on respective config files will also be placed. This way in future if any new configurations implemented can be easily added across all the modules.

Let’s assume we have a business component and it is referencing by all the modules (intention for this assumption is to remove duplicate code at all modules). 

Following is the static class RefreshConfigswhere it contains a static method Run() which implements the core logic. In this method, we first look for a setting called CentralAppConfigFilePath and get the CentralApp configuration file path. Once this file exists, we try to load this file along with respective app or web config file (each module will contain their own config file).  

<appSettings> 
    <!--Central Configuration effects both Service and application--> 
    <add key ="CentralAppConfigFilePath" value="D:\Configurations\CentralApp.config"/> 
  </appSettings>

 

public static class RefreshConfigs
    {
        public static void Run()
        {
            string centralAppConfigFilePath = Helper.GetAppSettingsKeyValue("CentralAppConfigFilePath");

            if (System.IO.File.Exists(centralAppConfigFilePath))
            {
                try
                {
                    XmlDocument xmlDoc_Source = new XmlDocument();
                    XmlDocument XmlDoc_Destination = new XmlDocument();
                    
                    xmlDoc_Source.Load(centralAppConfigFilePath);
                    XmlDoc_Destination.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                    
                    foreach (XmlElement xElement in xmlDoc_Source.DocumentElement.ChildNodes)
                    {
                        if(XmlDoc_Destination.DocumentElement.SelectSingleNode("//" + xElement.Name) != null)
                            XmlDoc_Destination.DocumentElement.RemoveChild(XmlDoc_Destination.SelectSingleNode("//" + xElement.Name));
                    
                        XmlDoc_Destination.DocumentElement.AppendChild(XmlDoc_Destination.ImportNode(xmlDoc_Source.SelectSingleNode("//" + xElement.Name), true));
                    }

                    //Saves config changes
                    XmlDoc_Destination.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

                    foreach (XmlElement xElement in xmlDoc_Source.DocumentElement.ChildNodes)
                    {
                        ConfigurationManager.RefreshSection(xElement.Name);
                    }
                    
                }
                catch
                {
                    throw;
                }
            }
        }
    }

Once XML files are loaded into their respective XML document objects, we try to remove the XML nodes (config elements) which are in central app configuration from the respective module-specific configuration file and then importing the configurations from the central app file.

Once all the configurations are imported, the module specific configuration file will be saved with modified configuration and then refreshes the existing configuration manager cache to reflect the new configuration changes.

We are ready with centralized configuration logic, now we need to call this method from any entry point methods in each module. Generally, it will be a program.cs file as follows.

Business.RefreshConfigs.Run();

Note: Make sure to have the CentralAppConfigFilePath app setting in all the module level web or app.config files as well as in CentralApp.config. As for the first time when central app configurations are imported existing app settings will be replaced and for the next time when any changes in the central app will not affect as  CentralAppConfigFilePath app setting is missing.

 

Hope you enjoyed this article…Thank you.