Read web.config section to List

7.7k views Asked by At

I have this in a web.config :

<MySection>
    <Setting1 Value="10" />
    <Setting2 Value="20" />
    <Setting3 Value="30" />
    <Setting4 Value="40" />
</MySection>

I'd like read the all section "MySection" and get all value to a List<string> (ex : "10","20","30")

Thanks,

3

There are 3 answers

3
abatishchev On BEST ANSWER

First of all, I recommend use to use Unity Configuration.

Code:

public class MySection : ConfigurationSection
{
    protected static ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();

    private static ConfigurationProperty propElements = new ConfigurationProperty("elements", typeof(MyElementCollection), null, ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsDefaultCollection);

    static BotSection()
    {
        properties.Add(propElements);
    }

    [ConfigurationProperty("elements", DefaultValue = null, IsRequired = true)]
    [ConfigurationCollection(typeof(MyElementCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
    public MyElementCollection Elements
    {
        get
        {
            return (MyElementCollection)this[propElements];
        }
        set
        {
            this[propElements] = value;
        }
    }
}

public class MyElementCollection : ConfigurationElementCollection, 
                                   IEnumerable<ConfigurationElement> // most important difference with default solution
{
    public void Add(MyElement element)
    {
        base.BaseAdd(element);
    }

    public void Clear()
    {
        base.BaseClear();
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new MyElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((MyElement)element).Id;
    }

    IEnumerator<MyElement> IEnumerable<MyElement>.GetEnumerator()
    {
        return this.OfType<MyElement>().GetEnumerator();
    }
}

public class MyElement : ConfigurationElement
{
    protected static ConfigurationPropertyCollection properties = new ConfigurationPropertyCollection();

    private static ConfigurationProperty propValue= new ConfigurationProperty("value", typeof(int), -1, ConfigurationPropertyOptions.IsRequired);

    public int Value
    {
        get
        {
            return (int)this[propValue];
        }
        set
        {
            this[propValue] = value;
        }
    }
}

Config:

<configuration>
    <configSections>
        <section name="MySection" type="MySection, MyAssembly"/>
    </configSections>
    <MySection>
        <elements>
            <clear />
            <add value="10" />
            <remove value="10" />
            <add value="20" />
            <add value="30" />
        </elements>
    </MySection>
</configuration>
1
Nathan Baulch On

I'd recommend you take a look at the excellent open source Configuration Section Designer project on CodePlex. It allows you to create custom configuration sections using a designer hosted in Visual Studio.

For example, a custom configuration section design like this:

Simple Custom Section will result in a configuration file like this:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="MySection" type="MyNamespace.MySection, MyAssembly"/>
  </configSections>
  <MySection xmlns="urn:MyNamespace">
    <MySetting Name="Test1" Value="One" />
    <MySetting Name="Test2" Value="Two" />
  </MySection>
</configuration>

which can be programmatically consumed like this:

foreach (MySetting setting in MySection.Instance.Items)
{
    Console.WriteLine("{0}: {1}", setting.Name, setting.Value);
}
0
Richard Squires On

For anyone else who found this answer like I did, I've refined the answer to use more standard parts of the ConfigurationManager mark-up to reduce the amount of boiler plate code required:

using System.Collections.Generic;
using System.Configuration;
using System.Linq;

namespace TestSite
{
    public class SiteConfiguration : ConfigurationSection
    {
        
        [ConfigurationProperty("listValues", DefaultValue = null, IsRequired = true)]
        [ConfigurationCollection(typeof(ListValues),
                                AddItemName = "add",
                                ClearItemsName = "clear",
                                RemoveItemName = "remove")]
        public ListValues ListValues
        {
            get { return (ListValues)this["listValues"]; }
            set { this["listValues"] = value; }
        }
    }

    /// <summary>
    /// Boilder plate holder for the collection of values
    /// </summary>
    public class ListValues : ConfigurationElementCollection, IEnumerable<ConfigurationElement>
    {
        protected override ConfigurationElement CreateNewElement() { return new ListElement(); }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ListElement)element).Value;
        }

        IEnumerator<ConfigurationElement> IEnumerable<ConfigurationElement>.GetEnumerator()
        {
            return this.OfType<ListElement>().GetEnumerator();
        }
    }

    /// <summary>
    /// Boilder plate holder for each value
    /// </summary>
    public class ListElement : ConfigurationElement
    {
        [ConfigurationProperty("value")]
        public string Value
        {
            get { return (string)this["value"]; }
            set { this["value"] = value; }
        }
    }
}

With the appropriate web.config:

<configSections>
    <section name="siteConfiguration" type="TestSite.SiteConfiguration, TestSite"/>
</configSections>
<siteConfiguration>
    <listValues>
        <clear/>
        <add value="one"/>
        <add value="two"/>
        <add value="three"/>
        <add value="four"/>
        <add value="five"/>
    </listValues>
</siteConfiguration>

Which can then be used like so:

            List<string> list = new List<string>();
            ListValues values = ((SiteConfiguration)ConfigurationManager.GetSection("siteConfiguration")).ListValues;
            foreach (ListElement elem in values)
            {
                list.Add(elem.Value);
            }

And voila, all the values are now in a list. (Tested in .Net Framework 4.8)