Using External Configuration Files in .NET Applications (C#)

This post is about making a small code snippet which read from an external configuration file and get the custom configuration entries from it.

I went through the solutions. My target was to checkout how we can use the external configuration files in an ASP.NET Web.config. The idea is that there are more than one web application is there in my own Virtual Organization. I thought of keeping a common configuration file for all those web application. So that I have to change configuration only in one place, from time to time changes.

1. Scenario 1 :- ASP.NET Application

Here is the solution I came across.

External configuration file(External.config), which will have some set of AppSettings key value pairs.

<?xml version="1.0"?>

<appSettings>

  <add key="Web_App_Name" value="Dream Works India"/>
  <add key="Web_App_ID" value="E1635BA6-0714-4496-A852-18868A0EB591"/>
</appSettings>

ASP.NET Web.config (Which refering to an external config file with name “External.config”)

<?xml version="1.0"?>
<configuration>
	<appSettings configSource="External.config"> <!-- Refering to an External Config File, You should specify the relative path -->
    
	</appSettings>
  
	<system.web>
		<compilation debug="true"/>
  </system.web>

</configuration>


Note: One thing you should make sure is that, in ASP.NET you have to mention the External config file’s relative path. It will not accept if i keep like “C:External.config”

ASP.NET – C# Code (for reading from external config file)

 

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace DreamWebSiteMain
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string Web_App_Name = WebConfigurationManager.AppSettings["Web_App_Name"];
            string Web_App_Id   = WebConfigurationManager.AppSettings["Web_App_ID"];


            string str = string.Empty;
        }
    }
}

That’s it. We are ready, here is the output i captured while debugging.

2. Scenario 2 :- Console/Windows Application

Here case is bit different from ASP.NET, you cannot simply specify in App.config file. Windows/Console Application would n’t work that way.

You will receive an exception if you try the same in console/windows application.

Error:- “Unable to initialize the configuration entries”
.

So what is other option we have. I came across a code-project article(link Specify a Configuration File at Runtime for a C# Console Application. That was really informative and thoughtful.

So i made slight changes to the code and implemented for my scenario.

External configuration file(C:External.config), which will have some set of AppSettings key value pairs.

<?xml version="1.0"?>

<appSettings>

  <add key="Web_App_Name" value="Dream Works India"/>
  <add key="Web_App_ID" value="E1635BA6-0714-4496-A852-18868A0EB591"/>
</appSettings>

Console Executable App.config (Which will not refering to an external config file with name “External.config”, leave it empty)

<?xml version="1.0"?>
<configuration>
	<appSettings > <!-- forget about linking external config here -->
    
	</appSettings>
  
	<system.web>
		<compilation debug="true"/>
  </system.web>

</configuration>


Note: One thing you should make sure is that, in ASP.NET you have to mention the External config file’s relative path. It will not accept if i keep like “C:External.config”

Console Application – C# Code (for reading from external config file)

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace DreamConsoleApp
{
    class Program
    {
        /// <summary>
        /// Mains the specified args.
        /// </summary>
        /// <param name="args">The args.</param>
        static void Main(string[] args)
        {
            SetConfigFileAtRuntime(@"C:External.config");  

            string Web_App_Name = ConfigurationManager.AppSettings["Web_App_Name"];
            string Web_App_Id = ConfigurationManager.AppSettings["Web_App_ID"];
            

            string str = string.Empty;
        }


        /// <summary>
        /// Sets the config file at runtime.
        /// </summary>
        /// <param name="configFilePath"></param>
        protected static void SetConfigFileAtRuntime(string configFilePath)
        {
            string runtimeconfigfile;

            if (configFilePath.Length == 0)
            {
                Console.WriteLine("Please specify a config file to read from ");
                Console.Write("> "); // prompt
                runtimeconfigfile = Console.ReadLine();
            }
            else
            {
                runtimeconfigfile = configFilePath;
            }

            // Specify config settings at runtime.
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            //Similarly you can apply for other sections like SMTP/System.Net/System.Web etc..
            //But you have to set the File Path for each of these 
            config.AppSettings.File = runtimeconfigfile;

            //This doesn't actually going to overwrite you Exe App.Config file.
            //Just refreshing the content in the memory.
            config.Save(ConfigurationSaveMode.Modified);

            //Refreshing Config Section
            ConfigurationManager.RefreshSection("appSettings");
        }

    }
}

That’s it. We are ready to go, here is the output i captured while debugging.

Voila!!!! Everything working as expected. I got the implementations for ASP.NET and Windows/Console App.

Hope this helps. I couldn’t get much time to do proper formatting. Hope you folks don’t mind the beauty of the code.

Happy Learning !!!!

3 Comments

  1. Pingback: FileSystemWatcher to Monitor when External configuration file is changed (C#) » Code Name "NitRiX Reloaded"

  2. How about persisting the changes in app.config? Its very hard to find any solution for this. You recognise “This doesn’t actually going to overwrite you Exe App.Config file”, which to me is the main issue. I need future sessions to know about changes made.

  3. Hi Robert;

    It is going to save the change back to the External app.config. I have tested this in few projects. We can save back the changes easily. Please see the code below. Hope this is self-explanatory.

    #region  Save(RallyConfigSection modifiedSection)
    
            /// <summary>
            /// Saves the specified modified section.
            /// </summary>
            /// <param name="modifiedSection">The modified section.</param>
            public static bool Save(MyConfigSection modifiedSection)
            {
                bool isSaveSuccess = false;
                try
                {
    
    
    
                    // Get the current configuration file.
                    //System.Configuration.Configuration config =
                           // ConfigurationManager.OpenExeConfiguration(
                           // ConfigurationUserLevel.None);
    
                    System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(GetConfigurationFilePath());
    
                    // Create a custom configuration section.
                    MyConfigSection customSection = config.GetSection(_configurationSectionConst) as MyConfigSection;
    
                    // Create the custom section entry  
                    // in <configSections> group and the 
                    // related target section in <configuration>.
                    if (config.Sections[_configurationSectionConst] == null)
                    {
                        customSection = modifiedSection;
                        config.Sections.Add(_configurationSectionConst, customSection);
                    }
                    else
                    {
                       //TO-DO: reassign modified values to the associated properties here.
    
    		    customSection.MyLoginConfig = modifiedSection.MyLoginConfig;
                        customSection.MyDatabaseConfig = modifiedSection.MyDatabaseConfig;
                        customSection.SectionInformation.ForceSave = true;
                    }
                    //customSection = modifiedSection;
    
                    // Create and add an entry to appSettings section.
    
    
    
                    // Save the configuration file.
                    customSection.SectionInformation.ForceSave = true;
                    config.Save(ConfigurationSaveMode.Full);
    
                    isSaveSuccess = true;
    
                    Console.WriteLine("Saved configuration file: {0}", config.FilePath);
    
                }
                catch (ConfigurationErrorsException err)
                {
                    isSaveSuccess = false;
                    Console.WriteLine("CreateConfigurationFile: {0}", err.ToString());
                }
    
                return isSaveSuccess;
            }
    
           
    #endregion
    

Other times, you're doing some piece of work and suddenly you get feedback that tells you that you have touched something that is very alive in the cosmos. Share your feedback on this blog, it will help me improve it a lot..