configurationconfiguration-filesconfigurationsection

Unrecognized attribute 'name' when using <remove /> in a ConfigurationElementCollection


I have a custom ConfigurationSection that contains a custom ConfigurationElementCollection with custom ConfigurationElement instances. The <add> and <clear> tags work fine in the configuration file, but using <remove> generates the following exception during my unit test:

System.Configuration.ConfigurationErrorsException: Unrecognized attribute 'name'. Note that attribute names are case-sensitive.

The configuration file is pretty simple. Here's the inner-part of the test section in question:

<exceptionHandling>
  <policies>
    <clear />
    <add name="default" shouldLog="true" shouldShow="true"/>
    <add name="initialization" shouldLog="true" shouldShow="true"/>
    <add name="security" shouldLog="true" shouldShow="true"/>
    <add name="logOnly" shouldLog="true" shouldShow="false"/>
    <add name="unhandled" shouldLog="true" shouldShow="true"/>
    <add name="test" shouldLog="false" shouldShow="false"/>
    <remove name="test"/>
  </policies>
</exceptionHandling>

The following is the relevant code for the configuration classes (some has been elided for brevity).

public sealed class ExceptionHandlingSection : ConfigurationSection
{
    [ConfigurationProperty("policies", IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(PolicyElementCollection), AddItemName = "add", RemoveItemName = "remove", ClearItemsName = "clear")]
    public PolicyElementCollection Policies => (PolicyElementCollection)base["policies"];
}

public sealed class PolicyElementCollection : ConfigurationElementCollection
{
   // pretty boiler plate
}

public sealed class PolicyElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsRequired = true)]
    public string Name
    {
        get => (string)this["name"];
        set => this["name"] = value;
    }

    // other properties
}

What needs to be done to get <remove> to work as shown in the test configuration file?


Solution

  • The answer to this turns out to be really simple.

    I read a few things talking about XML attributes, but fundamentally it's looking for a key property. This can be assigned by a property of the ConfigurationPropertyAttribute. To get the <remove> tag to work all I need to do is change my ConfigurationElement class as follows:

    public sealed class PolicyElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get => (string)this["name"];
            set => this["name"] = value;
        }
    
        // other properties
    }