Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

How to Implement Custom configSection with Nested Elements in C#

, 8 May 2014
Rate this:
Please Sign up or sign in to vote.
After completing this exercise, you should be able to implement custom configSection, with nested elements, in your application's config file.

Objective: After completing this exercise, you should be able to implement custom configSection, with nested elements, in your application’s config file.

In my previous post, How to implement custom configSection in your configuration, I have explained the details about how to implement simple single element based custom configSection in your configuration, i.e., without any nested elements.

However in many scenarios, we need to implement custom configSection having nested elements. It is very useful in cases where you need to store some limited number of configuration details or any data, and you do not want to use database for storing those configurations.

Here, I will explain the step by step process to implement custom configSection with nested elements. Like most of my posts, I have followed a practical approach rather than providing theory. Following this, you will be able to achieve the goal of the post.

Step 1: Create a new Console application named as “CustomNestedConfigSection”.

Step 2: Create a folder under this project named as “NestedConfig”.

Step 3: Add a new App.config file to the project.

Step 4: Add a new class file “EmployeesConfigSection.cs” in NestedConfig folder as below:

using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class EmployeesConfigSection : ConfigurationSection
    {
        //If you replace "employeeCollection" with "" then you do not need "employeeCollection" element as a wrapper node over employee nodes in config file.
        [ConfigurationProperty("employeeCollection", IsDefaultCollection = true, IsKey = false, IsRequired = true)]
        public EmployeeCollection Members
        {
            get
            {
                return base["employeeCollection"] as EmployeeCollection;
            }

            set
            {
                base["employeeCollection"] = value;
            }
        }

    }
}

Step 5: Add a new class file “EmployeeCollection.cs” in NestedConfig folder as below:

using System;
using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class EmployeeCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new Employee();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((Employee) element).Id;
        }

        protected override string ElementName
        {
            get
            {
                return "employee";
            }
        }

        protected override bool IsElementName(string elementName)
        {
            return !String.IsNullOrEmpty(elementName) && elementName == "employee";
        }

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

        public Employee this[int index]
        {
            get
            {
                return base.BaseGet(index) as Employee;
            }
        }

        public new Employee this[string key]
        {
            get
            {
                return base.BaseGet(key) as Employee;
            }
        }
    }
}

Step 6: Add a new class file “Employee.cs” in NestedConfig folder as below:

using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class Employee : ConfigurationElement
    {
        [ConfigurationProperty("id", IsKey = true)]
        public string Id { get { return (string) this["id"]; } }

        [ConfigurationProperty("personalInfo")]
        public PersonalInfo PersonalInfo
        {
            get { return (PersonalInfo)this["personalInfo"]; }
        }

        [ConfigurationProperty("homeAddress")]
        public Address HomeAddress { get { return (Address)this["homeAddress"]; } }

        [ConfigurationProperty("officeAddress")]
        public Address OfficeAddress { get { return (Address)this["officeAddress"]; } }
    }
}

Step 7: Add a new class file “PersonalInfo.cs” in NestedConfig folder as below:

using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class PersonalInfo : ConfigurationElement
    {
        [ConfigurationProperty("ssn", IsKey = true)]
        public string SSN { get { return (string)this["ssn"]; } set { this["ssn"] = value; } }

        [ConfigurationProperty("height")]
        public int Height { get { return (int)this["height"]; } set { this["height"] = value; } }

        [ConfigurationProperty("weight")]
        public int Weight { get { return (int)this["weight"]; } set { this["weight"] = value; } }
    }
}

Step 8: Add a new class file “Address.cs” in NestedConfig folder as below:

using System.Configuration;

namespace CustomNestedConfigSections.NestedConfig
{
    public class Address : ConfigurationElement 
    {
        [ConfigurationProperty("pin")]
        public string PinCode { get { return (string) this["pin"]; } }

        [ConfigurationProperty("city")]
        public string City { get { return (string)this["city"]; } }

        [ConfigurationProperty("state")]
        public string State { get { return (string)this["state"]; } }
    }
}

Step 9: Modify “App.config” file in your application as below:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="employeeCollectionSection" 
    type="CustomNestedConfigSections.NestedConfig.EmployeesConfigSection, 
    CustomNestedConfigSections"/>
  </configSections> 
  <employeeCollectionSection>
    <employeeCollection>
      <employee id="1">
        <personalInfo ssn="3243423" height="342"  weight="78" />
        <homeAddress pin="411001" city="Pune" state="Maharashtra"/>
        <officeAddress pin="844101" city="Shahdra" state="Delhi"/>
      </employee>
      <employee id="2">
        <personalInfo ssn="7435623" height="342" weight="62" />
        <homeAddress pin="411002" city="Pimpri" state="Maharashtra"/>
        <officeAddress pin="874785" city="Mangolpuri" state="Haryana"/>
      </employee>
    </employeeCollection>
  </employeeCollectionSection>
</configuration>

Step 10: Modify “Program.cs” file in your application as below:

using System;
using System.Configuration;
using CustomNestedConfigSections.NestedConfig;

namespace CustomNestedConfigSections
{
    class Program
    {
        static void Main(string[] args)
        {
            var employee1 = GetEmployee("1");
            Console.WriteLine("\n\nDetails of employee with id : 1");
            Console.WriteLine("Personal Info: SSN - {0} Height - {1}inch Weight - {2}Kg", 
            employee1.PersonalInfo.SSN, employee1.PersonalInfo.Height,employee1.PersonalInfo.Weight);
            Console.WriteLine("Home Address : {0} {1} {2}", employee1.HomeAddress.City, 
            employee1.HomeAddress.State, employee1.HomeAddress.PinCode);
            Console.WriteLine("Office Address : {0} {1} {2}", employee1.OfficeAddress.City, 
            employee1.OfficeAddress.State, employee1.OfficeAddress.PinCode);

            Console.ReadKey();
        }

        public static Employee GetEmployee(string employeeId)
        {
            var employeesConfigSection = ConfigurationManager.GetSection
            ("employeeCollectionSection") as EmployeesConfigSection;

            if (employeesConfigSection == null || 
            employeesConfigSection.Members == null || employeesConfigSection.Members.Count < 1)
                return null;

            return employeesConfigSection.Members[employeeId];
        }
    }
}

Step 11: Run your console application. Do not forget to add reference of “System.Configuration” in your console application project. I hope you will not get any error while running the application. However if you get one, you would be able to fix it.

Now I will explain the terms or points which have not been covered above.

  • For each element/node in your config, you need to create a corresponding class which derives from “ConfigurationElement”.
  • To define an attribute for any element/node, you need to create a public property with “ConfigurationProperty” attribute. For example, if you want to create an attribute named “city” for an element, then define a property like:
[ConfigurationProperty("city")]
public string City { get { return (string)this["city"]; } }
  • You define the name of element/node/attribute inside “ConfigurationProperty” attribute.
  • If you want more than one child node under an element or node, then you need to create a new class for that collection which should be derived from “ConfigurationElementCollection”. Here, you also define name of the element which represents your collection as I have created “employee" for employee collection.
  • To create root element/node for your configSection, you must create a class which derives from “ConfigurationSection”. To create simplest configSection, you need a single class derived from “ConfigurationSection” having properties, with ConfigurationProperty attribute, corresponding to required attributes.
  • If you do not want wrapper element/node for your collection, then replace ConfigurationProperty name with blank. For example, if you do not want “employeeCollection” element/node in your config file, then replace ConfigurationProperty name with blank from EmployeesConfigSection as below:
        //If you replace "employeeCollection" with "" then you do not need "employeeCollection" element as a wrapper node over employee nodes in config file.
        [ConfigurationProperty("", IsDefaultCollection = true, IsKey = false, IsRequired = true)]
        public EmployeeCollection Members
        {
            get
            {
                return base[""] as EmployeeCollection;
            }

            set
            {
                base[""] = value;
            }
        }

After making the above changes, configSection in your App.config file should be modified as:

  <employeeCollectionSection>
    <employee id="1">
      <personalInfo ssn="3243423" height="342"  weight="78" />
      <homeAddress pin="411001" city="Pune" state="Maharashtra"/>
      <officeAddress pin="844101" city="Shahdra" state="Delhi"/>
    </employee>
    <employee id="2">
      <personalInfo ssn="7435623" height="342" weight="62" />
      <homeAddress pin="411002" city="Pimpri" state="Maharashtra"/>
      <officeAddress pin="874785" city="Mangolpuri" state="Haryana"/>
    </employee>
  </employeeCollectionSection>
  • You will have n level of nesting of elements in this way. You will have n classes for n elements you need in your configuration.
  • You can define a static class for easy manipulation of configuration values. I have defined static methods in Program class for the purpose to get employee with given id.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Adarsh Chaurasia (Consultant|Mentor|Tech Savvy)
Software Developer (Senior)
India India
I have 4.6+ years of experience in SaaS, SOA based Enterprise Web Application design and development using Microsoft technology stack. I have mostly worked on Business layer, Data access layer, WCF, Entity Framework, Microsoft Application Blocks, Search engines, APIs integration, Third party APIs/Product Research & Development.
 
I am a huge fan of Design Patterns. I also work as Software Consultant. I read/write blogs, help and learn from other developers.
Follow on   Twitter   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 Pinmemberabeethadesilva1-Aug-14 1:53 
QuestionMembershipElement ? PinmemberMember 30687318-May-14 2:04 
AnswerRe: MembershipElement ? PinmemberAdarsh Kumar Chaurasia8-May-14 3:28 
GeneralRe: MembershipElement ? PinmemberMember 30687318-May-14 22:23 
GeneralRe: MembershipElement ? PinmemberAdarsh Kumar Chaurasia9-May-14 4:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 8 May 2014
Article Copyright 2014 by Adarsh Chaurasia (Consultant|Mentor|Tech Savvy)
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid