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?
9 réponses
Essayez
<add key="mykey" value="A,B,C"/>
Et
string[] mykey = ConfigurationManager.AppSettings["mykey"].Split(',');
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.
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 -
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).
Je pense que vous pouvez utiliser des Sections de configuration http://www.4guysfromrolla.com/articles/032807-1.aspx
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]
.
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>
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 :)
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
}
}