Implement custom section with a Configuration Element Collection c#

13,234

Solution 1

The problems appear to be in your app.config (or web.config). The element that contains your custom configuration XML must match the name you have specified in the name attribute in configSections\section. For example, for your code to work as written, the app.config should look something like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="s" type="Statistics.Config.DepartmentConfigurationSection, Program1"/>
  </configSections>
  <s>
    <Cash>
      <add Number="1" Name="Money" />
    </Cash>
    <Departments>
      <add Id="1" Name="x" />
      <add Id="2" Name="y" />
    </Departments>
  </s>
</configuration>

As you can see, the section name="s" matches the name of the s element. Also, you had the type listed as Statistics.Config.DeptartmentSection, but your class name is DepartmentConfigurationSection, so it should match the class you are trying to load.

Solution 2

I think you need to add class-level attribute at DepartmentCollection class with :

[DepartmentCollection(typeof(DepartmentConfig ), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap)]
Share:
13,234
puti26
Author by

puti26

Updated on June 04, 2022

Comments

  • puti26
    puti26 over 1 year

    I would like to implement a custom configuration section in a project. But something I don't understand so dont work.

    I have App.config that looks like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="DepartmentConfigurationSection" type="Statistics.Config.DepartmentSection , Program1"/>
      </configSections>
      <s>
        <Cash>
          <add Number="1" Name="Money" />
        </Cash>
        <Departments>
          <add Id="1" Name="x" />
          <add Id="2" Name="y" />
        </Departments>
      </s>
    </configuration>
    

    I create a file called DepartmentSection.cs that cointains the ConfigurationElement,ConfigurationElementCollection and the ConfigurationSection. The class is like this:

     public class DepartmentConfig : ConfigurationElement
        {
            public DepartmentConfig() { }
    
            public DepartmentConfig(int id, string name)
            {
                Id = id;
                Name = name;
            }
    
            [ConfigurationProperty("Id", IsRequired = true, IsKey = true)]
            public int Id
            {
                get { return (int)this["Id"]; }
                set { this["Id"] = value; }
            }
    
            [ConfigurationProperty("Name",  IsRequired = true, IsKey = false)]
            public string Name
            {
                get { return (string)this["Name"]; }
                set { this["Name"] = value; }
            }
        }
    
    
        public class DepartmentCollection : ConfigurationElementCollection
        {
            public DepartmentCollection()
            {
                Console.WriteLine("ServiceCollection Constructor");
            }
    
            public DepartmentConfig this[int index]
            {
                get { return (DepartmentConfig)BaseGet(index); }
                set
                {
                    if (BaseGet(index) != null)
                    {
                        BaseRemoveAt(index);
                    }
                    BaseAdd(index, value);
                }
            }
    
            public void Add(DepartmentConfig depConfig)
            {
                BaseAdd(depConfig);
            }
    
            public void Clear()
            {
                BaseClear();
            }
    
            protected override ConfigurationElement CreateNewElement()
            {
                return new DepartmentConfig();
            }
    
            protected override object GetElementKey(ConfigurationElement element)
            {
                return ((DepartmentConfig)element).Id;
            }
    
            public void Remove(DepartmentConfig depConfig)
            {
                BaseRemove(depConfig.Id);
            }
    
            public void RemoveAt(int index)
            {
                BaseRemoveAt(index);
            }
    
            public void Remove(string name)
            {
                BaseRemove(name);
            }
        }
    
    
        public class DepartmentConfigurationSection : ConfigurationSection
        {
            [ConfigurationProperty("Departments", IsDefaultCollection = false)]
            [ConfigurationCollection(typeof(DepartmentCollection),
                AddItemName = "add",
                ClearItemsName = "clear",
                RemoveItemName = "remove")]
            public DepartmentCollection Departments
            {
                get
                {
                    return (DepartmentCollection)base["Departments"];
                }
            }
        }
    

    I tried to get the collection from the handler but without success. I tried like this but give me this error: "Unable to initialize the system configuration".

        DepartmentConfigurationSection serviceConfigSection =
        ConfigurationManager.GetSection("s") as DepartmentConfigurationSection;
    
        DepartmentConfig serviceConfig = serviceConfigSection.Departments[0];
    
  • puti26
    puti26 about 10 years
    I corrected the errors but now appares this: " Error while creating the configuration section handler for s: Could not load type 'Program1.Config.DepartmentConfigurationSection' from assembly 'Program1'... Why?
  • rsbarro
    rsbarro about 10 years
    That means there's no class Program1.Config.DepartmentConfigurationSection in the Program1 assembly. What namespace is DepartmentConfigurationSection under? The type attribute should be type="[namespace], [assembly]", so in your case I think that should be type="Statistics.Config.DepartmentConfigurationSection, Program1".
  • puti26
    puti26 about 10 years
    The namespace is namespace Statistics.Config. What you mean when said no class in the Program1 assembly ?
  • rsbarro
    rsbarro about 10 years
    If the namespace is Statistics.Config, then the fully qualified name of the class is Statistics.Config.DepartmentConfigurationSection. The name of the assembly is Program1. So the type attribute should read type="Statistics.Config.DepartmentConfigurationSection, Program1".
  • rsbarro
    rsbarro about 10 years
    I meant what I said, there's no class named Program1.Config.DepartmentConfigurationSection in the Program1 assembly. The class is named Statistics.Config.DepartmentConfigurationSection. :)
  • puti26
    puti26 about 10 years
    Hi rsbarro, i update my app.config file, If i have another class called CashSection.cs equals DepartmentSection.cs. How i can use from handler both CashCollection and DepartmentsCollection? DepartmentConfigurationSection serviceConfigSection = ConfigurationManager.GetSection("s") as DepartmentConfigurationSection; DepartmentConfig serviceConfig = serviceConfigSection.Departments[0];
  • rsbarro
    rsbarro about 10 years
    If you have another config section, I think you want to add a another section element under configSections, and then just add a new config element, similar to how you did with the s element.
  • Patrick Hofman
    Patrick Hofman almost 10 years
    Please elaborate why you think this is a solution. Just code answers do bring a solution, but not understanding.