Steven Ball
Steven Ball

Reputation: 481

Custom app.config section error "Unrecognized element add"

I have a small app that searches my SQL Server database for the given value in all of the fields where it could be used. Part of that is a custom app.config section to hold all of these fields. However I'm getting an error on this line in the app:

var section = (DatabaseFieldSection)ConfigurationManager.GetSection("DatabaseFields");

app.config:

    <?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="DatabaseFields" type="PartyFinder.DataAccess.DatabaseFieldSection, DataAccess"/>
  </configSections>
  <connectionStrings>
    <!-- Data removed for security purposes -->
  </connectionStrings>
  <DatabaseFields>
    <add Key="Person.FirstName (SV)" TableName="dbo.Person" ColumnName="FirstName" FieldType="SV" />
  </DatabaseFields>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
</configuration>

Classes:

using System;
using System.Configuration;

namespace PartyFinder.DataAccess
{
    public class DatabaseFieldElement : ConfigurationElement
    {
        [ConfigurationProperty("Key", IsKey = true, IsRequired = true)]
        public string Key
        {
            get { return (string)base["Key"]; }
        }

        [ConfigurationProperty("TableName", IsKey = false, IsRequired = true)]
        public string TableName
        {
            get { return (string)base["TableName"]; }
        }

        [ConfigurationProperty("ColumnName", IsKey = false, IsRequired = true)]
        public string ColumnName
        {
            get { return (string)base["ColumnName"]; }
        }

        [ConfigurationProperty("FieldType", IsKey = false, IsRequired = true)]
        public string FieldType
        {
            get { return (string)base["FieldType"]; }
        }
    }

    public class DatabaseFieldSection : ConfigurationSection
    {
        [ConfigurationProperty("DatabaseFields", IsDefaultCollection = true)]
        [ConfigurationCollection(typeof(DatabaseFieldCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
        public DatabaseFieldCollection DatabaseFields
        {
            get { return ((DatabaseFieldCollection)base["DatabaseFields"]); }
        }
    }

    public class DatabaseFieldCollection : ConfigurationElementCollection
    {
        internal const string PropertyName = "Fields";

        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.AddRemoveClearMap;
            }
        }

        protected override string ElementName
        {
            get
            {
                return PropertyName;
            }
        }

        protected override bool IsElementName(string elementName)
        {
            return elementName.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase);
        }

        public override bool IsReadOnly()
        {
            return false;
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new DatabaseFieldElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((DatabaseFieldElement)(element)).Key;
        }

        public DatabaseFieldElement this[int id]
        {
            get
            {
                return (DatabaseFieldElement)BaseGet(id);
            }
        }
    }
}

I have done a ton of searches and nothing has worked so far. Any advice is much appreciated!

Upvotes: 1

Views: 4354

Answers (1)

DGibbs
DGibbs

Reputation: 14618

I managed to get the following to work in a console app by adding a parent DatabaseConfig node:

The DatabaseFieldSection class:

public class DatabaseFieldSection : ConfigurationSection
{
    public static DatabaseFieldSection GetConfig()
    {
        return (DatabaseFieldSection)System.Configuration.ConfigurationManager.GetSection("DatabaseConfig") ?? new DatabaseFieldSection();
    }

    [System.Configuration.ConfigurationProperty("DatabaseFields")]
    [ConfigurationCollection(typeof(DatabaseFieldCollection), AddItemName = "add")]
    public DatabaseFieldCollection DatabaseFields
    {
        get
        {
            object o = this["DatabaseFields"];
            return o as DatabaseFieldCollection;
        }
    }
}

And the App.config:

<configSections>
    <section name="DatabaseConfig" type="TestEnvironment.DBConfig.DatabaseFieldSection, TestEnvironment"/>
</configSections>
<DatabaseConfig>
    <DatabaseFields>
        <add Key="Person.FirstName (SV)" TableName="dbo.Person" ColumnName="FirstName" FieldType="SV" />
    </DatabaseFields>
</DatabaseConfig>

Usage:

var config = DatabaseFieldSection.GetConfig();

It seems as though the config <section /> cannot be the same as the config element collection name. e.g DatabaseFields, it needs to be:

Section > Collection > Items

Or:

DatabaseConfig > DatabaseFields > add

Upvotes: 3

Related Questions