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

Advertisement

, ,

  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 )

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: