Read/Write application’s config file

It is very often that you thought of writing values back to your .NET application’s config file would be more convenient. But the framework only provides the simple methods for reading from the config file, but when it comes to writing back to config file then framework does offers you anything. But it is not only easy to read values from config file but also to write value back to config file. At the end of the day, it’s XML ;-). In order to do this sort of things I will use a class that wraps up the ability to read and write values in the config file.

Warning: As a rule of thumb, it is not recommended to write values back to the config file. For a reason framework does not include this ability. For example, if you want your application’s users to not require any administrative rights then it is always a better idea to store settings in the user’s directory (documents and settings) or simply in the windows registry if necessary. This will avoid breaking anything and will become handy for utility applications.

Now, let’s move ahead. A .NET application’s cofig file is a text file that has a name of yourapplication.exe.config. The Visual Studio .NET IDE take lot of good care about you and your code and lets you add another config file named “App.config” in your project and will copy this config file to respective bin directory and will rename it to yourapplication.exe.config. This config file’s creation’s purpose is to store static values or settings for your application. As we all know now that it nothing more than XML.

Sample application config will look something like this

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="Val1" value="First value" />
        <add key="Val2" value="Second value" />
    </appSettings>
</configuration>

.NET Framework make programmer’s life very simple to read values from this config file. In System.Configuration namespace we have ConfigurationSettings class which includes the static AppSettings property which returns a NameValueCollection of name/value pairs. In order to get the value of “Val1” setting you can use following code:

string val1 = ConfigurationSettings.AppSettings["Val1"];

Piece of Cake, correct? It will allow you read settings from appSettings section only. In case if you add any other section(s) then you will not be able to read those sections using the above method (later section of post is for the same). As we done with reading part (partially), the main motive is to read / write everything in the config file.

Let’s start

To write values back in the config file, you have to open the config file as an XmlDocument and write. No rocket science. You leverage all properties and methods of XmlDocument to things like add name/value pairs, add/remove elements, edit them or whatever you want to do. The class below is defined to perform operations like read, write and remove settings from the appSettings section of the config file based on key or name of the setting.

using System;
using System.Xml;
using System.Configuration;
using System.Reflection;
//...

public class ConfigSettings
{
    private ConfigSettings() {}

    public static string ReadSetting(string key)
    {
        return ConfigurationSettings.AppSettings[key];
    }

    public static void WriteSetting(string key, string value)
    {
        // load config document for current assembly
        XmlDocument doc = loadConfigDocument();

        // retrieve appSettings node
        XmlNode node =  doc.SelectSingleNode("//appSettings");

        if (node == null)
            throw new InvalidOperationException("appSettings section not found in config file.");

        try
        {
            // select the 'add' element that contains the key
            XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key));

            if (elem != null)
            {
                // add value for key
                elem.SetAttribute("value", value);
            }
            else
            {
                // key was not found so create the 'add' element
                // and set it's key/value attributes
                elem = doc.CreateElement("add");
                elem.SetAttribute("key", key);
                elem.SetAttribute("value", value);
                node.AppendChild(elem);
            }
            doc.Save(getConfigFilePath());
        }
        catch
        {
            throw;
        }
    }

    public static void RemoveSetting(string key)
    {
        // load config document for current assembly
        XmlDocument doc = loadConfigDocument();

        // retrieve appSettings node
        XmlNode node =  doc.SelectSingleNode("//appSettings");

        try
        {
            if (node == null)
                throw new InvalidOperationException("appSettings section not found in config file.");
            else
            {
                // remove 'add' element with coresponding key
                node.RemoveChild(node.SelectSingleNode(string.Format("//add[@key='{0}']", key)));
                doc.Save(getConfigFilePath());
            }
        }
        catch (NullReferenceException e)
        {
            throw new Exception(string.Format("The key {0} does not exist.", key), e);
        }
    }

    private static XmlDocument loadConfigDocument()
    {
        XmlDocument doc = null;
        try
        {
            doc = new XmlDocument();
            doc.Load(getConfigFilePath());
            return doc;
        }
        catch (System.IO.FileNotFoundException e)
        {
            throw new Exception("No configuration file found.", e);
        }
    }

    private static string getConfigFilePath()
    {
        return Assembly.GetExecutingAssembly().Location + ".config";
    }
}

In order to use it, just use the static methods provided in the class as follows:

// read the Test1 value from the config file
string test1 = ConfigSettings.ReadSetting("Test1");

// write a new value for the Test1 setting
ConfigSettings.WriteSetting("Test1", "This is my new value");

// remove the Test1 setting from the config file
ConfigSettings.RemoveSetting("Test1");

Before you guys start cracking this, there are certain things to be aware of. First, this piece of code is written to handle windows applications config files. In order to make it work for a web application’s config file you just have to change the private static method that returns the name/location of the config file to something like this:

System.Web.HttpContext.Current.Server.MapPath("web.config");

You’d also need to make sure the ASP.NET process user account had access to write to that directory. I’d avoid doing this anyway, but still wanted to point this out.

Note: As a strong word of caution about editing the web.config file for a web application and I thought it was worth adding it to the post so it wouldn’t be missed. Every time you touch the web.config file the web app will recycle. Doing this often will throw performance out the window.

Secondly, in case you wanted to use this class into your own assembly/dll for re usability, then be aware that this class needs config file path based on executing assembly’s location. That means if this class is used in a DLL, it will be looking for DLL’s config file and not application’s. In order to solve this problem you can just pass the config file path as parameter in this class’s constructor.

All in all, an easy way to store configuration settings for your application. But heed my earlier warning. If your application is used by users in an AD, then you don’t want to have to give them elevated rights just to write back to your applications directory under Program Files. That’s what the Application Data directory is for under the users folder in Documents and Settings. Use it.

Posted in ASP.NET, Database, Programming Language, XML Tagged with: ,