Plusieurs valeurs pour une seule clé de configuration

J'essaie d'utiliser ConfigurationManager.AppSettings.GetValues() pour récupérer plusieurs valeurs de configuration pour une seule clé, mais je reçois toujours un tableau de seulement la dernière valeur. Mon appsettings.config ressemble à

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

Et j'essaie d'accéder avec

ConfigurationManager.AppSettings.GetValues("mykey");

Mais je ne reçois que { "C" }.

Des idées sur la façon de résoudre ce problème?

36
demandé sur Daniel Schierbeck 2010-05-12 18:54:01

9 réponses

Essayez

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

Et

string[] mykey = ConfigurationManager.AppSettings["mykey"].Split(',');
37
répondu Joel 2010-05-12 14:56:08

Le fichier de configuration traite chaque ligne comme une affectation, c'est pourquoi vous ne voyez que la dernière ligne. Quand il lit la configuration, il attribue à votre clé la valeur de "A", puis "B", puis "C", et puisque "C" est la dernière valeur, c'est celle qui colle.

Comme @Kevin le suggère, la meilleure façon de le faire est probablement une valeur dont le contenu est un CSV que vous pouvez analyser séparément.

9
répondu SqlRyan 2010-05-12 14:59:06

Je sais je suis en retard mais j'ai trouvé cette solution et cela fonctionne parfaitement donc je veux juste partager.

Il s'agit de définir votre propre 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"]; }
        }
    }
}

Et dans l'application.config utilisez simplement votre nouvelle 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>

Et lors de la récupération de données comme ceci :

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

Finalement, merci à l'auteur de l'original post -

9
répondu Wahid Bitar 2015-04-07 08:53:44

Ce que vous voulez faire n'est pas possible. Vous devez soit nommer chaque clé différemment, soit faire quelque chose comme value = "A, B, C" et séparer les différentes valeurs dans le code string values = value.split(',').

Il récupérera toujours la valeur de la clé qui a été définie en dernier (dans votre exemple C).

6
répondu kemiller2002 2010-05-12 14:54:50

Je pense que vous pouvez utiliser des Sections de configuration http://www.4guysfromrolla.com/articles/032807-1.aspx

3
répondu Lijo 2012-08-01 04:40:49

Puisque la méthode ConfigurationManager.AppSettings.GetValues() ne fonctionne pas, j'ai utilisé la solution de contournement suivante pour obtenir un effet similaire, mais avec la nécessité de suffixer les clés avec des index uniques.

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]);

Cela correspondra à des clés comme myKey[0] et myKey[1].

2
répondu Bart Verkoeijen 2014-11-12 09:52:13

Voici une solution complète: code dans 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;
            }
        }

    }
}

Et dans la configuration web

<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>
1
répondu Ajaya Nayak 2016-04-28 13:19:51

Mon point de vue sur la réponse de JJS: Fichier de configuration:

<?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 à récupérer dans la chaîne []

 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, c'est aussi simple que cela va être. Hésitez pas à me prouver le contraire :)

1
répondu user2981217 2017-03-06 23:35:52

J'utilise la convention de nommage des clés et cela fonctionne comme un charme

<?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
    }
}
1
répondu Cu Dao 2017-04-03 18:51:47