Geeks With Blogs

News



Microsoft Store

Support This Site


AddThis Social Bookmark Button

Locations of visitors to this page

Subscribers to this feed

TwitterCounter for @sdorman

Creative Commons License


Scott Dorman Microsoft MVP, Software Architect, Developer, Author

I spent most of yesterday trying to figure out how to make use of a NameValueCollection in a .NET configuration file. After wasting almost the entire night fighting with this problem, I thought I would let everyone know that it is possible, and easier than you might think. (By the way, this was a clear case of working too long on the problem. After a good nights sleep, I solved this in under 5 minutes.)

At this point you might wonder why this was so difficult. The largest and most significant problem is the fact that NameValueCollection isn't serializable (KB 814187). The reason for this is that NameValueCollection doesn't implement ICollection but extends NameObjectCollectionBase instead. The recommended solution is to use a SoapFormatter to serialize and deserialize the collection. While using the SoapFormatter does work, it seemed like a very complex solution for a seemingly simple problem.

Not wanting to over-engineer my solution, I started searching the web for alternatives. I found several newsgroup postings that all said to use the SoapFormatter since that was the recommended solution and the only way to go. Not having drunk too much blue kool-aid, I kept searching. That search turned up an article by Keyvan Nayyeri that shows how to created a serializable NameValueCollection. This approach was intriguing and certainly seemed to be a more useful solution than using the SoapFormatter, but again it seemed like a lot of work.

Keep in mind, all I wanted to be able to do in the configuration file was to create a section that looked like this:

   1: <copyFiles>
   2:   <add name="C:\Windows" value="*.dll"/>
   3:   <add name="C:\Temp"/>
   4: </copyFiles>

Continuing the search, I thought I found my answer. I stumbled across an article (".NET How To Create and Use Custom Name-Value Config Sections") that shows how to do this in 4 simple steps. Reading through the article, I realized that it is written using the the .NET 1.0 and 1.1 ConfigurationSettings, which is provided for backwards compatibility only. Since the application I'm working on is .NET 3.5 and taking advantage of many of the new language features, I wanted to ensure that I wasn't using any deprecated classes.

This is where I started running into additional problems. It seems that Microsoft provides a NameValueSectionHandler, which the article makes us of. The problem is that NameValueSectionHandler is architected following the .NET 1.0/1.1 model and implements the System.Configuration.IConfigurationSectionHandler interface. This is great if you want to use the deprecated ConfigurationSettings class; if you want to use the recommended System.Configuration.ConfigurationManager or System.Web.Configuration.WebConfigurationManager classes you are out of luck. They will only work with a class that derives from ConfigurationSection.

So, after all this I thought I was out of luck and would need to write my own configuration section handler. (Remember, this was about 1:00 AM.) After sleeping on it, I realized that there was a much simpler way. Along with the NameValueSectionHandler, Microsoft also implemented NameValueConfigurationCollection and NameValueConfigurationElement, which derive from the appropriate configuration classes to be used by the ConfigurationManager. After seeing that, I realized that all I needed to do was implement a NameValueSection which derives from ConfigurationSection.

This is where the solution becomes easy. In it's simplest most form, the NameValueSection looks like this:

   1: public class NameValueSection : ConfigurationSection
   2: {
   3:     [ConfigurationProperty("", IsDefaultCollection = true)]
   4:     public NameValueConfigurationCollection Settings
   5:     {
   6:         get
   7:         {
   8:             return (NameValueConfigurationCollection)base[""];
   9:         }
  10:     }
  11: }

As you can see, this is pretty simple. In order to use it, you declare the section in your app.config file:

   1: <sectionGroup name="customSettings">
   2:    <section name="copyFiles" type="NameValueSection, CustomConfiguration"/>
   3: </sectionGroup>
   4: <copyFiles>
   5:    <add name="C:\Windows" value="*.dll"/>
   6:    <add name="C:\Temp"/>
   7: </copyFiles>

To access this configuration section in code, you simply need to do this:

   1: NameValueSection nameValueSection = ConfigurationManager.GetSection("copyFiles") as NameValueSection;
   2: if (nameValueSection != null)
   3: {
   4:     NameValueConfigurationCollection settings = nameValueSection.Settings;
   5:     foreach (string key in settings.AllKeys)
   6:     {
   7:         Console.WriteLine(settings[key].Name + ": " + settings[key].Value);
   8:     }
   9: }

This is about as simple as it gets. Even though you aren't actually using the real NameValueCollection you are using the NameValueConfigurationCollection, which has almost identical behavior. This is the solution that I finally ended up implementing and it works great. As you can see, with a minimal amount of effort you are now able to use a NameValueCollection in your configuration files.

Posted on Sunday, March 16, 2008 8:00 PM .NET (General) , .NET (C#) | Back to top


Comments on this post: NameValueCollection and .NET Configuration Files

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
For the above sample to build I had to change the following (VS 2008):
1) encapsulate the copyFiles section into a customSettings section like:
<customSettings>
<copyFiles>
<add name="C:\Windows" value="*.dll"/>
<add name="C:\Temp"/>
</copyFiles>
</customSettings>

2) Also add this parent section into the GetSection call like in:
= ConfigurationManager.GetSection("customSettings/copyFiles")
Left by Sébastien Gillet on Apr 30, 2008 6:55 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
when i ran above sample i got the error
"An error occurred creating the configuration section handler for customSettings/copyFiles: Could not load file or assembly 'CustomConfiguration' or one of its dependencies. The system cannot find the file specified." Any idea?

Thanks,
Left by Ben on Oct 03, 2008 5:16 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Ben, You need to ensure that System.Configuration is listed as a reference in your project.
Left by Scott on Nov 15, 2008 10:21 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Why not use a custom AppSettingsSection?

<configSections>
<sectionGroup name="customSettings">
<section name="copyFiles" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</sectionGroup>
</configSections>
<customSettings>
<copyFiles>
<add key="C:\Windows" value="*.dll"/>
<add key="C:\Temp"/>
</copyFiles>
</customSettings>

NameValueCollection settings = ConfigurationManager.GetSection("customSettings/copyFiles") as NameValueCollection;
if (settings != null)
{
foreach (string key in settings.AllKeys)
{
Response.Write(key + ": " + settings[key] + "<br />");
}
}
Left by UTCD on Jan 28, 2009 11:03 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
NameValueCollection settings = ConfigurationManager.GetSection("customSettings/copyFiles") as NameValueCollection;

I was using above logic and encountered an error "Cannot load the config file".
Left by Naresh on Feb 06, 2009 10:33 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Thank you! I have made it.
Left by Jingle on Nov 22, 2009 11:15 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Scott,
Great solution! I am converting an app that uses extensive registry entries to use a custom config file. I couldn't access a NameValue Collection from the custom configuration until I found your solution.
Thank you!
Left by Rich Jardine on Apr 30, 2010 2:35 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
I try use this in my Addin VS, load a config file and I get this error:


//System.Configuration.ConfigurationErrorsException: Unrecognized attribute 'key'. Note that attribute names are case-sensitive. (E:\TFS\pro\RealeTeam\Main\Public\RealeDevelopment\RealeAddIn\bin\Debug\RealeAddIn.dll.config line 10)
// NameValueSection nameValueSection = config.GetSection("ImpersonationSettings") as NameValueSection;

THX
Left by kique net on Sep 15, 2011 8:20 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
very good example! thanks
Left by stenly on Sep 26, 2011 9:26 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Great post ... you nailed it!!! I spent the better part of 3 days browsing the net, finding many of the same solutions you found in your search. I find MSDN to be pretty good as a reference tool, but pretty lacking in the "show me how to ..." department. Finally, I came across your solution. Thanks so much ... it was a huge help.
Left by David on Nov 04, 2011 5:59 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
Excellent post by Scott! I was struggling with a similar problem and he helped me to solve it. But my issue requires adding new NameValue pair at run time. Here is how I do it.

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

NameValueSection section = config.GetSection("customSettings/copyFiles") as NameValueSection;

if (section != null)
{
section.Add("Name", "Value");

config.Save(ConfigurationSaveMode.Modified);
}

public class NameValueSection : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
public NameValueConfigurationCollection Settings
{
get
{
return (NameValueConfigurationCollection)base[""];
}
}

public void Add(string name, string value)
{
Settings.Add(new NameValueConfigurationElement(name, value));
}
}
Left by Jim on Jan 17, 2012 4:57 PM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
This absolutely doesn't work for me. My code is identical and I am constantly getting the following error no matter what I change in the app.config.

Could not load file or assembly 'CustomConfiguration' or one of its dependencies. The system cannot find the file specified.
Left by ALH on Mar 03, 2013 10:48 AM

# re: NameValueCollection and .NET Configuration Files
Requesting Gravatar...
great post scott, very helpful. however i am experiencing a small difficulty.

" if(section != null) "

... can anyone tell me why my section IS infact null? I have copied this code exactly, and i dont understand how or why it could be null?
Left by Kev on Nov 25, 2014 11:11 AM

Your comment:
 (will show your gravatar)


Copyright © Scott Dorman | Powered by: GeeksWithBlogs.net | Join free