Saving settings to XML Configuration Files

Posted by Marco Minerva

Some times ago I published a class that allows to read XML Configurtion Files (.config) in the standard .NET format. Now, I am asked how to change and save these settings back to file.

So, I have updated the ConfigurationManager class to support these new features.

public static class ConfigurationManager
{
    private const string APPSETTINGS_SECTION = "appSettings";
    private const string ADD = "add";
    private const string KEY = "key";
    private const string VALUE = "value";

    private static Hashtable appSettings;

    static ConfigurationManager()
    {
        appSettings = new Hashtable();
    }

    public static string GetAppSetting(string key)
    {
        return GetAppSetting(key, null);
    }

    public static string GetAppSetting(string key, string defaultValue)
    {
        if (!appSettings.Contains(key))
            return defaultValue;

        return (string)appSettings[key];
    }

    public static void SetAppSetting(string key, string value)
    {
        appSettings[key] = value;
    }

    public static void Load(Stream xmlStream)
    {
        appSettings.Clear();
        using (XmlReader reader = XmlReader.Create(xmlStream))
        {
            while (reader.Read())
            {
                switch (reader.Name)
                {
                    case APPSETTINGS_SECTION:
                        while (reader.Read())
                        {
                            if (reader.Name == APPSETTINGS_SECTION)
                                break;

                            if (reader.Name == ADD)
                            {
                                var key = reader.GetAttribute(KEY);
                                var value = reader.GetAttribute(VALUE);

                                //Debug.Print(key + "=" + value);
                                appSettings.Add(key, value);
                            }
                        }

                        break;
                }
            }
        }
    }

    public static void Save(Stream xmlStream)
    {
        using (StreamWriter writer = new StreamWriter(xmlStream))
        {
            writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
            writer.WriteLine("<configuration>");
            writer.WriteLine("\t<appSettings>");

            foreach (DictionaryEntry item in appSettings)
            {
                string add = "\t\t<add key=\"" + item.Key + "\" value=\"" + item.Value + "\" />";
                writer.WriteLine(add);
            }

            writer.WriteLine("\t</appSettings>");
            writer.WriteLine("</configuration>");
        }
    }
}

There are two new methods: SetAppSetting and Save. The former is used to add settings and modify existing ones, while the latter saves the configuration file (tipically on a SD card). To write the file, we use a StreamWriter to create the XML based on the hastable contents.

Its usage is very simple. Create a new .NET Gadgeteer application and connect the SD Card and a button module to the FEZ Spider. In the root of the SD Card, put the following configuration file with the name Application.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSetting>
    <add key="Key1" value="Value1" />
    <add key="Key2" value="Value2" />
    <add key="Key3" value="Value3" />
    <add key="hostName" value="www.google.it" />
    <add key="port" value="25" />
  </appSettings>
</configuration>

Finally, in the Program.cs file, we write the code to use the ConfigurationManager class.

using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;
using System.IO;

namespace AppSettingsRWExample
{
    public partial class Program
    {
        private const string FILE_PATH = "Application.config";

        // This method is run when the mainboard is powered up or reset.
        void ProgramStarted()
        {
            sdCard.SDCardMounted += new SDCard.SDCardMountedEventHandler(sdCard_SDCardMounted);
            button.ButtonPressed += new Button.ButtonEventHandler(button_ButtonPressed);

            Debug.Print("Program Started");
        }

        private void sdCard_SDCardMounted(SDCard sender, GT.StorageDevice SDCard)
        {
            // Reads configuration file.
            using (Stream configStream = SDCard.OpenRead(FILE_PATH))
            {
                // Loads settings.
                ConfigurationManager.Load(configStream);
            }

            // Retrieves some values.
            var host = ConfigurationManager.GetAppSetting("HostName");
            var port = ConfigurationManager.GetAppSetting("Port");
            var userName = ConfigurationManager.GetAppSetting("Username", "anonymous");

            Debug.Print("HostName: " + host);
            Debug.Print("Port: " + port);
            Debug.Print("Username: " + userName);

        }

        private void button_ButtonPressed(Button sender, Button.ButtonState state)
        {
            // Changes an existing value in the file.
            ConfigurationManager.SetAppSetting("HostName", "http://www.netmf.com/gadgeteer");

            // Adds a value that contains the last save time.
            ConfigurationManager.SetAppSetting("LastSaveTime", DateTime.Now.ToString());

            // Saves settings.
            using (Stream configStream = sdCard.GetStorageDevice().OpenWrite(FILE_PATH))
            {
                ConfigurationManager.Save(configStream);
            }

            Debug.Print("Settings saved");
        }
    }
}

In this code, we read configuration settings when the memory card in inserted into the module, as described in the previous post. Then, when we press the button, the button_Pressed event is raised. First al all, we use the new SetAppSetting method: we overwrite a value (HostName) that already exsits and add a new one (LastSaveTime). Finally, we invoke the Save method, passing the stream that represents the file in which to write all the settings.

This application is available for download.

AppSettingsRWExample.zip

, ,

  1. #1 by JayJay on March 25, 2012 - 8:51 AM

    Thank you for the new updated config class….
    Awesom…

  2. #3 by Craig on September 30, 2013 - 3:34 AM

    thanks for the class, note you have a typo on the appsettings section of the config file “appSetting” should be “appSettings”

  3. #4 by Alan Hartmann on March 13, 2014 - 2:16 PM

    Thanks, this was a big help!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: