1

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

garfbradaz
  • 3,424
  • 7
  • 43
  • 70
  • 1
    I think the issue is that your `ConfigurationSection` is not a `ConfigurationElementCollection` – DavidG Oct 19 '15 at 09:41
  • @DavidG: Firstly thank you for your speedy reply, appreciated. Do you mean where I have used the attribute '[ConfigurationCollection(typeof..'? – garfbradaz Oct 19 '15 at 09:48
  • @DavidG: Sounds good. Just to confirm, do you mean: http://chat.stackoverflow.com/ – garfbradaz Oct 19 '15 at 09:57
  • Thanks @DavidG for all of your help - I will update the post later to explain what I did. Create a post and I will mark as answered :) – garfbradaz Oct 19 '15 at 11:38

1 Answers1

2

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

DavidG
  • 113,891
  • 12
  • 217
  • 223
  • The first statement of this answer is wrong. The root element can be the collection holder quite easily. The extra level is unnecessary. See https://stackoverflow.com/a/14782024/426379 – Saul Jun 25 '17 at 15:40
  • It looks to me more like the attribute on the collection class specified the type of the collection `typeof(EncryptedUserCredentials)` rather than the type of the element `typeof(EncryptedUserCredential)`. – Suncat2000 Apr 25 '19 at 20:03