Working on a VSTO Outlook addin. I need to store configuration parameters in an XML file. I am struggling with some basic config file loading issue. I would appreciate a fresh view:
customConfiguration.xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="CDSSettings" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<CDSSettings>
<add key="APIusername" value="myUser" />
<add key="APIpassword" value="myPassword" />
</CDSSettings>
<appSettings>
<add key="logLevel" value="0" />
</appSettings>
</configuration>
Code
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "customConfiguration.xml";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
AppSettingsSection appSettingsSection = (config.GetSection("appSettings") as AppSettingsSection);
// --> All ok
ConfigurationSection CDSSettings = (ConfigurationSection)config.GetSection("CDSSettings");
// --> How to get the APIusername key?
Any chance I can avoid an XML parser or SectionInformation.GetRawXml()?
Can't explain why ConfigurationManager.GetSection
and config.GetSection
returns different results object
, that can be converted to NameValueCollection
in first case, and section that is DefaultSection in second
.
I would suggest to create a custom section and use it:
public class CDSSettings : ConfigurationSection
{
[ConfigurationProperty("MyValues")]
public KeyValueConfigurationCollection MyValues
{
get { return (KeyValueConfigurationCollection) this["MyValues"]; }
set { this["MyValues"] = value; }
}
}
and config will looks like
<section name="CDSSettings" type="UCAddin.CDSSettings, UCAddin" />
...
<CDSSettings>
<MyValues>
<add key="APIusername" value="myUser" />
<add key="APIpassword" value="myPassword" />
</MyValues>
</CDSSettings>
Retrieve code:
var CDSSettings = (CDSSettings)config.GetSection("CDSSettings");
More In case of custom section you can also specify different types of fields e.g. you can have separate named element:
public class Credentials : ConfigurationElement
{
[ConfigurationProperty("login")]
public string Login
{
get { return (string)this["login"]; }
set { this["login"] = value; }
}
}
with named proerties
[ConfigurationProperty("credentials")]
public Credentials Credentials
{
get { return (Credentials) this["credentials"]; }
set { this["credentials"] = value; }
}
and config will looks like
<CDSSettings>
<credentials login="testlogin" />
</CDSSettings>
Check this MSDN article for more possibilities
As AppSettings You can register property as default collection
public class CDSSettings : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
public KeyValueConfigurationCollection MyValues =>
(KeyValueConfigurationCollection) this[string.Empty];
}
and have parameters as in App Settings
<CDSSettings>
<add key="login" value="User" />
</CDSSettings>
But in code those data will be accessible from the property (if you'll not implement indexer in the class)
var settings = (CDSSettings)config.GetSection("CDSSettings");
settings.MyValues