I'm trying to write a very simple custom configuration section for a .NET4 application. My goal is this:
<configuration>
<configSections>
<section name="myServices" type="My.ConfigSection, My.Assembly" />
</configSections>
<myServices>
<add name="First" />
<add name="Second" />
</myServices>
</configuration>
However, I keep getting a ConfigurationErrorsException
: 'Unrecognized element 'add'' when I call ConfigurationManager.GetSection("myServices")
. I've been staring at it for a while now but haven't figured out yet what I'm doing wrong. Below is my code. It's three classes: ConfigSection
, MyServiceSettingsCollection
and MyServiceSettings
.
First the class that represents the entire config section. It has a nameless default collection of type MyServiceSettingsCollection
. The IsDefaultCollection
property should allow me to 'add' directly to my collection from the root element.
public sealed class ConfigSection : ConfigurationSection
{
private static readonly ConfigurationProperty _propMyServices;
private static readonly ConfigurationPropertyCollection _properties;
public static ConfigSection Instance { get { return _instance; } }
static ConfigSection()
{
_propMyServices = new ConfigurationProperty(
null, typeof(MyServiceSettingsCollection), null,
ConfigurationPropertyOptions.IsDefaultCollection);
_properties = new ConfigurationPropertyCollection { _propMyServices };
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public MyServiceSettingsCollection MyServices
{
get { return (MyServiceSettingsCollection) base[_propMyServices]; }
set { base[_propMyServices] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return _properties; } }
}
Next, the collection class itself. It is of type AddRemoveClearMap
.
[ConfigurationCollection(typeof(MyServiceSettings),
CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public sealed class MyServiceSettingsCollection : ConfigurationElementCollection
{
public MyServiceSettings this[int index]
{
get { return (MyServiceSettings) BaseGet(index); }
set
{
if (BaseGet(index) != null) { BaseRemoveAt(index); }
BaseAdd(index, value);
}
}
public new MyServiceSettings this[string key]
{
get { return (MyServiceSettings) BaseGet(key); }
}
protected override ConfigurationElement CreateNewElement()
{
return new MyServiceSettings();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MyServiceSettings) element).Key;
}
}
And finally a class for the elements in the collection. For now, this class has one property but there will be more later (which prevents me from using NameValueSectionHandler
).
public class MyServiceSettings : ConfigurationElement
{
private static readonly ConfigurationProperty _propName;
private static readonly ConfigurationPropertyCollection properties;
static MyServiceSettings()
{
_propName = new ConfigurationProperty("name", typeof(string), null, null,
new StringValidator(1),
ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey);
properties = new ConfigurationPropertyCollection { _propName };
}
[ConfigurationProperty("name", DefaultValue = "",
Options = ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey)]
public string Name
{
get { return (string) base[_propKey]; }
set { base[_propKey] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return properties; } }
}
We will start with creating an class that can store the instance settings (the <add> element), then we'll create a collection that can store our instances (the <instances> element) and then we'll create the class to manage the Configuration Section (the <sageCRM> element).
config file includes settings that apply to all of the ASP.NET applications that run a specific version of the . NET Framework. Because each ASP.NET application inherits default configuration settings from the root Web.
Ok, I found the seemingly random fix. Instead of this:
[ConfigurationProperty("", IsDefaultCollection = true)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }
you should use:
[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }
No idea what the difference is between the two. To me, they look strikingly similar... or at least, there is no suggestion anywhere why one is preferred over the other.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With