How to read from and write to an app.Config or web.Config using C#

There are a number of ways you can do this. In this example I will use the ConfigurationManager libraries that are part of the .Net Framework. This group of methods and properties are created specifically for this purpose. I am a firm believer that every action we want to take as a programmer needs to be done using the correct library. It would be possible to use the System.IO library and open the file write to it and then close it but this would not be best practice. There are many ways to design and program computer systems, but every way is not right and just because it works does not make it a good one.

Another design principle I like to use is trying not to create customized controls or programs if the class, method or property already exists. Having worked in a support organization for many years, I can confirm that resolving issues with custom code is exponentially more complex than “out of the box” code. So when deciding where I was going to write my data to resulted in determining whether to create a custom section or use the AppSettings section.

A review of the custom section creation logic it was much cooler. It was object oriented, I could implement an enum and could inherit from the ConfigurationElement and ConfigurationSection classes. My decision was to keep it simple even though the alternative was an interesting proposition, but my support side kicked in and I decided to use the built in capabilities of the AppSettings section.

This example is not what I implemented, it is what I created as a proof of concept that I created prior to customizing it to meet the project requirements.

I wanted to do 3 things:

  • Write to the AppSettings of the configuration file
  • Read all the AppSettings within the configuration file
  • Get a specific value from the configuration file based on the key

I created these 3 methods to perform the above:

[sourcecode language="csharp" padlinenumbers="true" autolinks="false" gutter="false" toolbar="false"]
public void ReadAllAppSettings()
{
    try
    {
        NameValueCollection appSettings = 
                  ConfigurationManager.AppSettings;
 
        if (appSettings.Count == 0)
        {
         Console.WriteLine("ReadAppSettings: {0}", 
            "The AppSettings section is empty.");
            Console.WriteLine();
        }
 
        for (int i = 0; i > appSettings.Count; i++)
        {
            Console.WriteLine(
                "ReadAppSettings: {0} Key: {1} Value: {2}", 
                i,
                appSettings.GetKey(i), appSettings[i]);
            Console.WriteLine();
        }
    }
    catch (ConfigurationErrorsException e)
    {
        Console.WriteLine("ReadAppSettings: {0}", 
                          e.ToString());
        Console.WriteLine();
    }
}
[/sourcecode]

The ReadAllAppSettings method uses the ConfigurationManager AppSettings property to get data in the AppSettings section of the configuration file. Here is a specific example of using “out of the box” functionality. I did not have to do anything other than populate the appSettings variable to get all the data I needed. Then I simply check the count or loop through and project the key value pairs and catch any error.

[sourcecode language="csharp" autolinks="false" gutter="false" toolbar="false"]
public void CreateAppSettings(string sectionName, 
                              string key, string value)
{
    try
    {
        Configuration config = 
         ConfigurationManager.OpenExeConfiguration
                               (ConfigurationUserLevel.None);
 
        config.AppSettings.Settings.Add(key, value);
        config.Save();
        ConfigurationManager.RefreshSection(sectionName);
    }
    catch (ConfigurationErrorsException e)
    {
        Console.WriteLine("[CreateAppSettings: {0}]", 
                          e.ToString());
        Console.WriteLine();
    }
}
[/sourcecode]

The CreateAppSettings method is the method that creates the entry within the AppSettings section. The RefreshSection is required because I want to read from it after I write to before restarting the program. Without the refresh we can not read the newly created data.

[sourcecode language="csharp" autolinks="false" gutter="false" toolbar="false"]
public string GetAppSettingValue(string key)
{
    try
    {
        NameValueCollection appSettings = 
             ConfigurationManager.AppSettings;
 
        string[] arr = appSettings.GetValues(key);
        return arr[0];
    }
    catch (ConfigurationErrorsException e)
    {
        Console.WriteLine("[CreateAppSettings: {0}]", 
                          e.ToString());
        Console.WriteLine();
        return e.ToString();
    }
    catch (Exception e)
    {
        Console.WriteLine("[CreateAppSettings: {0}]", 
                          e.ToString());
        Console.WriteLine();
        return e.ToString();
    }
}
[/sourcecode]

And lastly, I create a method to get a specific value within the AppSettings section based on the key, which is passed into the method. You can see that I have 2 catch blocks. While I was testing what would happen if the CreateAppSettings method did not call the RefreshSection method I got an exception which the ConfigurationErrorsExcpetion did not catch. So I added the catch all Exception class.

One important note that caused me some confusion when I was running this was that after I ran the program I looked at the configuration file and did not see any values added.

Basically when running from within Visual Studio the data is inserted into the appName.vshost.exe.config. BIG NOTE: once the program stops to data will vanish from this file too. You need to leave the program running when you look into the appName.vshost.exe.config file to see the data you added to the AppSection of the configuration file. However, when you distribute your application you only need to ship the appName.exe.config file along with the executable and the data will be written and remain in the configuration file as expected.

Download the source.



Leave a Comment

Your email address will not be published.