71

I'm working with C#, Framework 3.5 (VS 2008).

I'm using the ConfigurationManager to load a config (not the default app.config file) into a Configuration object.

Using the Configuration class, I was able to get a ConfigurationSection, but I could not find a way to get the values of that section.

In the config, the ConfigurationSection is of type System.Configuration.NameValueSectionHandler.

For what it worth, when I used the method GetSection of the ConfigurationManager (works only when it was on my default app.config file), I received an object type, that I could cast into collection of pairs of key-value, and I just received the value like a Dictionary. I could not do such cast when I received ConfigurationSection class from the Configuration class however.

EDIT: Example of the config file:

<configuration>
  <configSections>
    <section name="MyParams" 
             type="System.Configuration.NameValueSectionHandler" />
  </configSections>

  <MyParams>
    <add key="FirstParam" value="One"/>
    <add key="SecondParam" value="Two"/>
  </MyParams>
</configuration>

Example of the way i was able to use it when it was on app.config (the "GetSection" method is for the default app.config only):

NameValueCollection myParamsCollection =
             (NameValueCollection)ConfigurationManager.GetSection("MyParams");

Console.WriteLine(myParamsCollection["FirstParam"]);
Console.WriteLine(myParamsCollection["SecondParam"]);
SteveC
  • 15,808
  • 23
  • 102
  • 173
Liran B
  • 711
  • 1
  • 5
  • 4

8 Answers8

30

Suffered from exact issue. Problem was because of NameValueSectionHandler in .config file. You should use AppSettingsSection instead:

<configuration>

 <configSections>
    <section  name="DEV" type="System.Configuration.AppSettingsSection" />
    <section  name="TEST" type="System.Configuration.AppSettingsSection" />
 </configSections>

 <TEST>
    <add key="key" value="value1" />
 </TEST>

 <DEV>
    <add key="key" value="value2" />
 </DEV>

</configuration>

then in C# code:

AppSettingsSection section = (AppSettingsSection)ConfigurationManager.GetSection("TEST");

btw NameValueSectionHandler is not supported any more in 2.0.

nerijus
  • 516
  • 5
  • 11
  • 9
    Casting to AppSettings section didn't worked for me. Instead, i've casted to NameValueCollection and worked. – Jone Polvora Sep 28 '14 at 07:10
  • I had a little bit trouble to get my section working (some mistakes while loading the config file itself), but after that this solution worked perfectly. Now I can split my config file in multiple sections and easily access the values via AppSettingsSection. – Onsokumaru Feb 04 '19 at 13:33
19

Here's a good post that shows how to do it.

If you want to read the values from a file other than the app.config, you need to load it into the ConfigurationManager.

Try this method: ConfigurationManager.OpenMappedExeConfiguration()

There's an example of how to use it in the MSDN article.

Taryn
  • 242,637
  • 56
  • 362
  • 405
MonkeyWrench
  • 1,809
  • 2
  • 24
  • 48
  • 6
    As i said in my post, This is what i did. I received Configuraion class, and from it i received a ConfigurationSection. My question was how can i get the values from that ConfigurationSection object? i didn't ask how to get the Configuration object.. Thanks anyway! – Liran B Aug 11 '10 at 20:32
  • 2
    by the way, in the example you gave me they are not using the Configuration class that comes from OpenMappedExeConfiguration, but they are using the default app.config (which can be used using the .GetSection/.GetConfig methods, but as i said in my post- i did that already. but its no good for me since its good for app.config only). and for the msdn, i could not find the answer to my question there.. – Liran B Aug 11 '10 at 20:35
  • Ok, the more I look into it, the more I see it isn't easy to do. The basic problem is that you're trying to mix .Net 1.1 configuration style code and 2.0. Read this, it'll point you in the right direction: http://www.eggheadcafe.com/software/aspnet/30832856/backwards-compatibility-of-systemconfigurationconfiguration.aspx – MonkeyWrench Aug 12 '10 at 13:37
  • 1
    @MonkeyWrench The page is no more available. – Hari Nov 06 '14 at 06:25
  • Looks like bluefeet fixed that. Thanks. – MonkeyWrench Feb 02 '15 at 22:01
  • Aw... why the downvote? I can't fix the internet. The link is 5 years old. The MSDN has a good example as well. – MonkeyWrench Feb 24 '15 at 16:20
  • 2
    This answer appears to be suffering from link rot, this is why [link only answers are discouraged](http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers). – Liam Jul 22 '15 at 15:58
  • Great blog post. Thanks for sharing. – RayLoveless Sep 28 '16 at 16:11
  • Downvote: It's a good answer in general about the config topic for the beginner/standard usecase, but it's a useless answer for the specific problem of the initial question. I ran into the same problem as Liran B and the blogpost helps absolutely not. The question is how to deal with the `ConfigurationSection`-object. – Onsokumaru Feb 04 '19 at 12:29
  • not working on my side – aj go Jan 12 '22 at 10:05
16

Try using an AppSettingsSection instead of a NameValueCollection. Something like this:

var section = (AppSettingsSection)config.GetSection(sectionName);
string results = section.Settings[key].Value;

Source: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d5079420-40cb-4255-9b3b-f9a41a1f7ad2/

Steven Ball
  • 461
  • 1
  • 5
  • 18
  • 5
    nope this way you will get "Unable to cast object of type 'System.Configuration.DefaultSection' to type 'System.Configuration.AppSettingsSection'." – nerijus Mar 04 '13 at 14:23
  • 4
    @nerijus : come on man ... Of course one of Steven's assumptions is that you actually change the type of the section accordingly ... No offense, but you really could think before commenting. I tried this solution and it works. +1 for Steven – h9uest Apr 03 '13 at 14:58
  • 2
    @h9uest: It's not so straightforward, as Liran wrote the section is `System.Configuration.NameValueSectionHandler`. This answer seems more like a kind-of-dirty hack. – Peter Ivan Oct 03 '13 at 08:17
8

The only way I can get this to work is to manually instantiate the section handler type, pass the raw XML to it, and cast the resulting object.

Seems pretty inefficient, but there you go.

I wrote an extension method to encapsulate this:

public static class ConfigurationSectionExtensions
{
    public static T GetAs<T>(this ConfigurationSection section)
    {
        var sectionInformation = section.SectionInformation;

        var sectionHandlerType = Type.GetType(sectionInformation.Type);
        if (sectionHandlerType == null)
        {
            throw new InvalidOperationException(string.Format("Unable to find section handler type '{0}'.", sectionInformation.Type));
        }

        IConfigurationSectionHandler sectionHandler;
        try
        {
            sectionHandler = (IConfigurationSectionHandler)Activator.CreateInstance(sectionHandlerType);
        }
        catch (InvalidCastException ex)
        {
            throw new InvalidOperationException(string.Format("Section handler type '{0}' does not implement IConfigurationSectionHandler.", sectionInformation.Type), ex);
        }

        var rawXml = sectionInformation.GetRawXml();
        if (rawXml == null)
        {
            return default(T);
        }

        var xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(rawXml);

        return (T)sectionHandler.Create(null, null, xmlDocument.DocumentElement);
    }
}

The way you would call it in your example is:

var map = new ExeConfigurationFileMap
{
    ExeConfigFilename = @"c:\\foo.config"
};
var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var myParamsSection = configuration.GetSection("MyParams");
var myParamsCollection = myParamsSection.GetAs<NameValueCollection>();
Steven Padfield
  • 644
  • 1
  • 5
  • 12
  • It's so nice to see somebody answering the question asked. I have been digging through reams of answers to questions about handling OpenExeConfiguration GetSection with "answers" that redirect people to ConfigurationManager.GetSection which doesn't so the same thing. – Joseph May 15 '18 at 13:27
  • You should be able to just call the Get method: var myParamsCollection = myParamsSection.Get(); – nivs1978 May 28 '20 at 08:23
  • When I try the above I'm getting "Unable to find section handler type..." error. In your example what does the XML look like? I'm using the OP XML "
    "
    – wavydavy Apr 11 '22 at 08:43
4

This is an old question, but I use the following class to do the job. It's based on Scott Dorman's blog:

public class NameValueCollectionConfigurationSection : ConfigurationSection
{
    private const string COLLECTION_PROP_NAME = "";

    public IEnumerable<KeyValuePair<string, string>> GetNameValueItems()
    {
        foreach ( string key in this.ConfigurationCollection.AllKeys )
        {
            NameValueConfigurationElement confElement = this.ConfigurationCollection[key];
            yield return new KeyValuePair<string, string>
                (confElement.Name, confElement.Value);
        }
    }

    [ConfigurationProperty(COLLECTION_PROP_NAME, IsDefaultCollection = true)]
    protected NameValueConfigurationCollection ConfCollection
    {
        get
        {
            return (NameValueConfigurationCollection) base[COLLECTION_PROP_NAME];
        }
    }

The usage is straightforward:

Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
NameValueCollectionConfigurationSection config = 
    (NameValueCollectionConfigurationSection) configuration.GetSection("MyParams");

NameValueCollection myParamsCollection = new NameValueCollection();
config.GetNameValueItems().ToList().ForEach(kvp => myParamsCollection.Add(kvp));
Peter Ivan
  • 1,467
  • 2
  • 14
  • 27
3

Here are some examples from this blog mentioned earlier:

<configuration>    
   <Database>    
      <add key="ConnectionString" value="data source=.;initial catalog=NorthWind;integrated security=SSPI"/>    
   </Database>    
</configuration>  

get values:

 NameValueCollection db = (NameValueCollection)ConfigurationSettings.GetConfig("Database");         
    labelConnection2.Text = db["ConnectionString"];

-

Another example:

<Locations 
   ImportDirectory="C:\Import\Inbox"
   ProcessedDirectory ="C:\Import\Processed"
   RejectedDirectory ="C:\Import\Rejected"
/>

get value:

Hashtable loc = (Hashtable)ConfigurationSettings.GetConfig("Locations"); 

labelImport2.Text = loc["ImportDirectory"].ToString();
labelProcessed2.Text = loc["ProcessedDirectory"].ToString();
RayLoveless
  • 19,880
  • 21
  • 76
  • 94
0

Try this;

Credit: https://www.limilabs.com/blog/read-system-net-mailsettings-smtp-settings-web-config

SmtpSection section = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");

string from = section.From;
string host = section.Network.Host;
int port = section.Network.Port;
bool enableSsl = section.Network.EnableSsl;
string user = section.Network.UserName;
string password = section.Network.Password;
Sedat Kumcu
  • 2,191
  • 1
  • 17
  • 13
0

This works like a charm

dynamic configSection = ConfigurationManager.GetSection("MyParams");
var theValue = configSection["FirstParam"];
aj go
  • 637
  • 2
  • 10
  • 27