Multiple values for a single config key

.Netasp.netConfiguration

.Net Problem Overview


I'm trying to use ConfigurationManager.AppSettings.GetValues() to retrieve multiple configuration values for a single key, but I'm always receiving an array of only the last value. My appsettings.config looks like

<add key="mykey" value="A"/>
<add key="mykey" value="B"/>
<add key="mykey" value="C"/>

and I'm trying to access with

ConfigurationManager.AppSettings.GetValues("mykey");

but I'm only getting { "C" }.

Any ideas on how to solve this?

.Net Solutions


Solution 1 - .Net

Try

<add key="mykey" value="A,B,C"/>

And

string[] mykey = ConfigurationManager.AppSettings["mykey"].Split(',');

Solution 2 - .Net

The config file treats each line like an assignment, which is why you're only seeing the last line. When it reads the config, it assigns your key the value of "A", then "B", then "C", and since "C" is the last value, it's the one that sticks.

as @Kevin suggests, the best way to do this is probably a value whose contents are a CSV that you can parse apart.

Solution 3 - .Net

I know I'm late but i found this solution and it works perfectly so I just want to share.

It's all about defining your own ConfigurationElement

namespace Configuration.Helpers
{
    public class ValueElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get { return (string) this["name"]; }
        }
    }

    public class ValueElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new ValueElement();
        }


        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ValueElement)element).Name;
        }
    }

    public class MultipleValuesSection : ConfigurationSection
    {
        [ConfigurationProperty("Values")]
        public ValueElementCollection Values
        {
            get { return (ValueElementCollection)this["Values"]; }
        }
    }
}

And in the app.config just use your new section:

<configSections>
	<section name="PreRequest" type="Configuration.Helpers.MultipleValuesSection,
	Configuration.Helpers" requirePermission="false" />
</configSections>

<PreRequest>
	<Values>
		<add name="C++"/>
		<add name="Some Application"/>
	</Values>
</PreRequest>

and when retrieving data just like this :

var section = (MultipleValuesSection) ConfigurationManager.GetSection("PreRequest");
var applications = (from object value in section.Values
					select ((ValueElement)value).Name)
					.ToList();

Finally thanks to the author of the original post

Solution 4 - .Net

What you want to do is not possible. You either have to name each key differently, or do something like value="A,B,C" and separate out the different values in code string values = value.split(',').

It will always pick up the value of the key which was last defined (in your example C).

Solution 5 - .Net

I use naming convention of the keys and it works like a charm

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="section1" type="System.Configuration.NameValueSectionHandler"/>
  </configSections>
  <section1>
    <add key="keyname1" value="value1"/>
    <add key="keyname21" value="value21"/>
    <add key="keyname22" value="value22"/>
  </section1>
</configuration>

var section1 = ConfigurationManager.GetSection("section1") as NameValueCollection;
for (int i = 0; i < section1.AllKeys.Length; i++)
{
    //if you define the key is unique then use == operator
    if (section1.AllKeys[i] == "keyName1")
    {
        // process keyName1
    }

    // if you define the key as a list, starting with the same name, then use string StartWith function
    if (section1.AllKeys[i].Startwith("keyName2"))
    {
        // AllKeys start with keyName2 will be processed here
    }
}

Solution 6 - .Net

I think, you can use Custom Config Sections http://www.4guysfromrolla.com/articles/032807-1.aspx

Solution 7 - .Net

Since the ConfigurationManager.AppSettings.GetValues() method is not working, I've used the following workaround to get a similar effect, but with the need to suffix the keys with unique indexes.

var name = "myKey";
var uniqueKeys = ConfigurationManager.AppSettings.Keys.OfType<string>().Where(
    key => key.StartsWith(name + '[', StringComparison.InvariantCultureIgnoreCase)
);
var values = uniqueKeys.Select(key => ConfigurationManager.AppSettings[key]);

This will match keys like myKey[0] and myKey[1].

Solution 8 - .Net

Here is full solution: code in aspx.cs

namespace HelloWorld
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            UrlRetrieverSection UrlAddresses = (UrlRetrieverSection)ConfigurationManager.GetSection("urlAddresses");
        }
    }

    public class UrlRetrieverSection : ConfigurationSection
    {
        [ConfigurationProperty("", IsDefaultCollection = true,IsRequired =true)]
        public UrlCollection UrlAddresses
        {
            get
            {
                return (UrlCollection)this[""];
            }
            set
            {
                this[""] = value;
            }
        }
    }

  
    public class UrlCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new UrlElement();
        }
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((UrlElement)element).Name;
        }
    }

    public class UrlElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
        public string Name
        {
            get
            {
                return (string)this["name"];
            }
            set
            {
                this["name"] = value;
            }
        }

        [ConfigurationProperty("url", IsRequired = true)]
        public string Url
        {
            get
            {
                return (string)this["url"];
            }
            set
            {
                this["url"] = value;
            }
        }

    }
}

And in web config

<configSections>
   <section name="urlAddresses" type="HelloWorld.UrlRetrieverSection" />
</configSections>
<urlAddresses>
    <add name="Google" url="http://www.google.com" />
   <add name="Yahoo"  url="http://www.yahoo.com" />
   <add name="Hotmail" url="http://www.hotmail.com/" />
</urlAddresses>

Solution 9 - .Net

My take on JJS's reply: Config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="List1" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    <section name="List2" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <List1>
    <add key="p-Teapot" />
    <add key="p-drongo" />
    <add key="p-heyho" />
    <add key="p-bob" />
    <add key="p-Black Adder" />
  </List1>
  <List2>
    <add key="s-Teapot" />
    <add key="s-drongo" />
    <add key="s-heyho" />
    <add key="s-bob"/>
    <add key="s-Black Adder" />
  </List2>
  
</configuration>

Code to retrieve into string[]

 private void button1_Click(object sender, EventArgs e)
    {

        string[] output = CollectFromConfig("List1");
        foreach (string key in output) label1.Text += key + Environment.NewLine;
        label1.Text += Environment.NewLine;
        output = CollectFromConfig("List2");
        foreach (string key in output) label1.Text += key + Environment.NewLine;
    }
    private string[] CollectFromConfig(string key)
    {
        NameValueCollection keyCollection = (NameValueCollection)ConfigurationManager.GetSection(key);
        return keyCollection.AllKeys;
    }

IMO, that's as simple as it is going to get. Feel free to prove me wrong :)

Solution 10 - .Net

I found the solution to be very simple. If all keys are going to have the same value, simply use the unique values as the keys and omit the value.

<configSections>
    <section name="appSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
    <section name="filelist" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
 </configSections>

<filelist>
    <add key="\\C$\Temp\File01.txt"></add>
    <add key="\\C$\Temp\File02.txt"></add>
    <add key="\\C$\Temp\File03.txt"></add>
    <add key="\\C$\Temp\File04.txt"></add>
    <add key="\\C$\Temp\File05.txt"></add>
    <add key="\\C$\Temp\File06.txt"></add>
    <add key="\\C$\Temp\File07.txt"></add>
    <add key="\\C$\Temp\File08.txt"></add>
</filelist>

Then in code simply use the following:

private static List<string> GetSection(string section)
        {
            NameValueCollection sectionValues = ConfigurationManager.GetSection(section) as NameValueCollection;

            return sectionValues.AllKeys.ToList();
        }

The result is:

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel SchierbeckView Question on Stackoverflow
Solution 1 - .NetJoelView Answer on Stackoverflow
Solution 2 - .NetSqlRyanView Answer on Stackoverflow
Solution 3 - .NetWahid BitarView Answer on Stackoverflow
Solution 4 - .Netkemiller2002View Answer on Stackoverflow
Solution 5 - .NetCu DaoView Answer on Stackoverflow
Solution 6 - .NetLCJView Answer on Stackoverflow
Solution 7 - .NetBart VerkoeijenView Answer on Stackoverflow
Solution 8 - .NetAjaya NayakView Answer on Stackoverflow
Solution 9 - .Netuser2981217View Answer on Stackoverflow
Solution 10 - .NetBLaminackView Answer on Stackoverflow