Skip to main content

My ASP.NET web site settings class for storing and retrieving configuration settings in an XML file (settings.xml). It uses the Singleton design pattern and is fairly simple to customize.
And here's what your settings.xml config file should look like.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Web;
using System.Xml;

public sealed class SiteSettings
{
    #region - Site Settings -

    private SiteSettings()
    {
        Load();
    }

    #region - Setting File -

    public const string DefaultStorageLocation = "App_Data";
    public const string DefaultFilename = "settings.xml";

    private string SettingsFile;

    #endregion

    #region - Instance -

    private static readonly object _lock = new object();
    private static SiteSettings _siteSettings;

    public static SiteSettings Instance
    {
        get
        {
            if (_siteSettings == null)
            {
                lock (_lock)
                {
                    if (_siteSettings == null)
                    {
                        _siteSettings = new SiteSettings();
                    }
                }
            }

            return _siteSettings;
        }
    }

    #endregion

    #endregion

    #region - Properties -

    public string SiteTitle { get; set; }
    public string ContactEmail { get; set; }
    public string Stage { get; set; }
    public string SmtpServer { get; set; }
    public DateTime Modified { get; private set; }

    #region - Version -

    private static string _version;

    public string Version()
    {
        return _version ?? (_version = GetType().Assembly.GetName().Version.ToString());
    }

    #endregion

    #endregion

    #region - Changed -

    /// <summary>
    ///   Occurs when the settings have been [changed].
    /// </summary>
    public static event EventHandler<EventArgs> Changed;

    private static void OnChanged()
    {
        if (Changed != null)
        {
            Changed(null, EventArgs.Empty);
        }
    }

    #endregion

    #region - Load -

    private IDictionary<String, PropertyInfo> GetSettingsTypePropertyDict()
    {
        Type settingsType = GetType();

        var result = new Dictionary<String, PropertyInfo>(StringComparer.OrdinalIgnoreCase);

        foreach (PropertyInfo prop in settingsType.GetProperties())
        {
            result[prop.Name] = prop;
        }

        return result;
    }

    private void Load()
    {
        SettingsFile = HttpContext.Current.Server.MapPath(
            string.Format("{0}{1}{2}",
                DefaultStorageLocation,
                Path.DirectorySeparatorChar,
                DefaultFilename)
        );

        StringDictionary dic = LoadSettings(SettingsFile);
        IDictionary<string, PropertyInfo> settingsProps = GetSettingsTypePropertyDict();

        foreach (DictionaryEntry entry in dic)
        {
            var name = (string) entry.Key;
            PropertyInfo property;
            if (settingsProps.TryGetValue(name, out property))
            {
                try
                {
                    if (property.CanWrite)
                    {
                        var value = (string) entry.Value;
                        Type propType = property.PropertyType;
                        if (propType.IsEnum)
                        {
                            property.SetValue(this, Enum.Parse(propType, value), null);
                        }
                        else
                        {
                            property.SetValue(this, Convert.ChangeType(value, propType, CultureInfo.CurrentCulture), null);
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(string.Format("Error loading site settings: {0}", e.Message));
                }
            }
        }
    }

    private static StringDictionary LoadSettings(string filename)
    {
        var dic = new StringDictionary();
        var doc = new XmlDocument();

        doc.Load(filename);

        XmlNode settings = doc.SelectSingleNode("settings");
        if (settings != null)
        {
            foreach (XmlNode settingsNode in settings.ChildNodes)
            {
                string name = settingsNode.Name;
                string value = settingsNode.InnerText;
                dic.Add(name, value);
            }
        }

        return dic;
    }

    #endregion

    #region - Save -

    /// <summary>
    ///   Saves the settings to the file store.
    /// </summary>
    public void Save()
    {
        var sd = new StringDictionary();
        Type settingsType = GetType();

        Modified = DateTime.Now;

        foreach (PropertyInfo propertyInformation in settingsType.GetProperties())
        {
            if (propertyInformation.Name != "Instance")
            {
                object propertyValue = propertyInformation.GetValue(this, null);
                string valueAsString;
                if (propertyValue == null
                    || propertyValue.Equals(Int32.MinValue)
                    || propertyValue.Equals(Single.MinValue))
                {
                    valueAsString = String.Empty;
                }
                else
                {
                    valueAsString = propertyValue.ToString();
                }
                sd.Add(propertyInformation.Name, valueAsString);
            }
        }

        SaveSettings(sd, SettingsFile);

        OnChanged();
    }

    private static void SaveSettings(StringDictionary settings, string filename)
    {
        var writerSettings = new XmlWriterSettings { Indent = true };
        using (XmlWriter writer = XmlWriter.Create(filename, writerSettings))
        {
            writer.WriteStartElement("settings");
            foreach (string key in settings.Keys)
            {
                writer.WriteElementString(key, settings[key]);
            }
            writer.WriteEndElement();
        }
    }

    #endregion

}