garfbradaz
garfbradaz

Reputation: 3490

Custom App.Config Section - Unrecognized element Exception

I'm trying to create a Custom Section in the app.config and run into the following exception:

ConfigurationErrorsException

Unrecognized element 'EncryptedUserCredential'. (C:\My Documents\Hachette.CRM\test_app_appsettings\bin\Debug\test_app_appsettings.vshost.exe.Config line 11)

Now I'm at a complete loss. I have stepped into the RegisterEncryptedUserCredentialsConfig.GetConfig(), and found the Section is null from the propery RegisterEncryptedUserCredentialsConfig.EncryptedUserCredentials. I have also checked all the usual suspects I when investigating online, like:

  1. Making sure the type includes the assembly name in the app.config configSection when declaring the custom section.
  2. is at the beginning of in the app.config.

The custom section is written in:

  1. Class Library
  2. C#/.NET 4.0.

I'm at a loss and think I have been staring at it too long the weekend gone and need some fresh eyes!

For ease I have added all the code from the C# class library here.

Here is the app.config:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="EncryptedUserCredentials"
             type="Hachette.Common.CustomConfigSections.RegisterEncryptedUserCredentialsConfig, Hachette.Common"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <EncryptedUserCredentials>
    <EncryptedUserCredential userName="garethB" password="1235@"/>
    <EncryptedUserCredential userName="webService" password="123ffff5@"/>
  </EncryptedUserCredentials>
</configuration>

Here is the EncryptedUserCredential ConfigurationElement:

public class EncryptedUserCredential : ConfigurationElement
{
    [ConfigurationProperty("userName", IsRequired = true)]
    public string UserName
    {
        get
        {
            return this["userName"] as string;
        }
    }

    [ConfigurationProperty("password", IsRequired = true)]
    public string Password
    {
        get
        {
            return this["password"] as string;
        }
    }
}

Here is the EncryptedCredentials ConfigurationElementCollection:

public class EncryptedUserCredentials : ConfigurationElementCollection
{
    public EncryptedUserCredential this[int index]
    {
        get
        {
            return base.BaseGet(index) as EncryptedUserCredential;
        }
        set
        {
            if (base.BaseGet(index) != null)
            {
                base.BaseRemoveAt(index);
            }
            this.BaseAdd(index, value);
        }
    }

    public new EncryptedUserCredential this[string responseString]
    {
        get
        {
            return (EncryptedUserCredential)BaseGet(responseString);
        }
        set
        {
            if (BaseGet(responseString) != null)
            {
                BaseRemoveAt(BaseIndexOf(BaseGet(responseString)));
            }
            BaseAdd(value);
        }
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((EncryptedUserCredential)element).UserName;
    }
}

Here is the RegisterEncryptedUserCredentialsConfig ConfigurationSection:

public class RegisterEncryptedUserCredentialsConfig : ConfigurationSection
{
    public static RegisterEncryptedUserCredentialsConfig GetConfig()
    {
        //var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

        return (RegisterEncryptedUserCredentialsConfig)System.Configuration.ConfigurationManager.GetSection("EncryptedUserCredentials") ?? new RegisterEncryptedUserCredentialsConfig();
    }

    [System.Configuration.ConfigurationProperty("EncryptedUserCredentials", IsDefaultCollection=true,IsRequired=true)]
    [ConfigurationCollection(typeof(EncryptedUserCredentials), AddItemName="EncryptedUserCredential")]
    public EncryptedUserCredentials EncryptedUserCredentials
    {
        get
        {
            object o = this["EncryptedUserCredentials"];
            return o as EncryptedUserCredentials;
        }


    }

}

All of the above live in namespace:

namespace Hachette.Common.CustomConfigSections

And in the following Assembly:

enter image description here

Upvotes: 1

Views: 5013

Answers (1)

DavidG
DavidG

Reputation: 118937

It's not possible for the root element to be the collection holder. So you should code up your configuration to match this structure (note I've picked a name for the root element to match your namespace, but feel free to choose anything you like):

<hachette>
  <EncryptedUserCredentials>
    <EncryptedUserCredential userName="garethB" password="1235@"/>
    <EncryptedUserCredential userName="webService" password="123ffff5@"/>
  </EncryptedUserCredentials>
</hachette>

This means your configuration hierarchy will have a root ConfigSection which in turn contains a ConfigurationElementCollection that contains all of the ConfigurationElement objects.

Here is an example article on how you can write it: http://www.abhisheksur.com/2011/09/writing-custom-configurationsection-to.html

Upvotes: 2

Related Questions