Salim
Salim

Reputation: 505

C# XML config file custom section always null

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()?

Upvotes: 2

Views: 818

Answers (1)

ASpirin
ASpirin

Reputation: 3651

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

Upvotes: 1

Related Questions