How to: Create Custom Configuration Sections Using IConfigurationSectionHandler

You can extend the standard set of ASP.NET configuration settings with XML configuration elements of your own. To do this, you must create your own configuration section handler.

The handler must be a .NET Framework class that implements either the System.Configuration.IConfigurationSectionHandler interface or the System.Configuration.ConfigurationSection class.

Note

This topic uses the System.Configuration.IConfigurationSectionHandler interface, which has been deprecated in the .NET Framework version 2.0. For an example that uses the System.Configuration.ConfigurationSection class, see How to: Create Custom Configuration Sections Using ConfigurationSection. If you use the following code examples, please build them with the .NET Framework version 1.0 or 1.1.

The section handler interprets and processes the settings defined in XML configuration elements within a specific portion of a Web.config file and returns an appropriate configuration object based on the configuration settings. The configuration object that the handler class returns can be any data structure; it is not limited to any base configuration class or configuration format. ASP.NET uses the configuration object to read and write to your custom configuration element.

To create a custom configuration section handler

  1. Create a public class that implements the System.Configuration.IConfigurationSectionHandler interface, as illustrated in the following code.

    Imports System
    Imports System.Collections
    Imports System.Text
    Imports System.Configuration
    Imports System.Xml
    
    Namespace MyConfigSectionHandler
      Public Class MyHandler
        Implements IConfigurationSectionHandler
    
        Public Function Create( _
        ByVal parent As Object, ByVal configContext As Object, ByVal section As System.Xml.XmlNode) _
        As Object Implements System.Configuration.IConfigurationSectionHandler.Create
    
          Throw New System.Exception("The method is not implemented.")
    
        End Function 
      End Class 
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Configuration;
    using System.Xml;
    
    namespace MyConfigSectionHandler
    {
      public class MyHandler : IConfigurationSectionHandler
      {
        #region IConfigurationSectionHandler Members
    
        object IConfigurationSectionHandler.Create(
            object parent, object configContext, XmlNode section)
        {
          throw new Exception("The method is not implemented.");
        }
    
        #endregion
      }
    }
    
  2. Add your own code to perform the configuration work that you desire.

    For example, you can replace the throw new Exception("The method is not implemented."); line with code that obtains the attribute names and values from the Attributes property of the section parameter, and return a custom configuration object. The following example uses a Hashtable as the configuration object.

    Imports System
    Imports System.Collections
    Imports System.Text
    Imports System.Configuration
    Imports System.Xml
    
    Namespace MyConfigSectionHandler
    
      Public Class MyHandler
        Implements IConfigurationSectionHandler
    
        Public Function Create( _
        ByVal parent As Object, ByVal configContext As Object, ByVal section As System.Xml.XmlNode) _
        As Object Implements System.Configuration.IConfigurationSectionHandler.Create
    
          ' Creates the configuration object that this method will return. 
          ' This can be a custom configuration class. 
          ' In this example, we use a System.Collections.Hashtable. 
          Dim myConfigObject As New Hashtable
    
          ' Gets any attributes for this section element. 
          Dim myAttribs As New Hashtable
          For Each attrib As XmlAttribute In section.Attributes
            If XmlNodeType.Attribute = attrib.NodeType Then
              myAttribs.Add(attrib.Name, attrib.Value)
            End If 
          Next 
    
          ' Puts the section name and attributes as the first config object item.
          myConfigObject.Add(section.Name, myAttribs)
    
          ' Gets the child element names and attributes. 
          For Each child As XmlNode In section.ChildNodes
            If XmlNodeType.Element = child.NodeType Then 
              Dim myChildAttribs As New Hashtable
    
              For Each childAttrib As XmlAttribute In child.Attributes
                If XmlNodeType.Attribute = childAttrib.NodeType Then
                  myChildAttribs.Add(childAttrib.Name, childAttrib.Value)
                End If 
              Next
              myConfigObject.Add(child.Name, myChildAttribs)
            End If 
          Next 
    
          Return (myConfigObject)
    
        End Function 
    
      End Class 
    
    End Namespace
    
    using System;
    using System.Collections;
    using System.Text;
    using System.Configuration;
    using System.Xml;
    
    namespace MyConfigSectionHandler
    {
      public class MyHandler : IConfigurationSectionHandler
      {
        #region IConfigurationSectionHandler Members
    
        object IConfigurationSectionHandler.Create(
          object parent, object configContext, XmlNode section)
        {
          // Creates the configuration object that this method will return. 
          // This can be a custom configuration class. 
          // In this example, we use a System.Collections.Hashtable.
          Hashtable myConfigObject = new Hashtable();
    
          // Gets any attributes for this section element.
          Hashtable myAttribs = new Hashtable();
          foreach (XmlAttribute attrib in section.Attributes)
          {
            if (XmlNodeType.Attribute == attrib.NodeType)
              myAttribs.Add(attrib.Name, attrib.Value);
          }
    
          // Puts the section name and attributes as the first config object item.
          myConfigObject.Add(section.Name, myAttribs);
    
          // Gets the child element names and attributes. 
          foreach (XmlNode child in section.ChildNodes)
          {
            if (XmlNodeType.Element == child.NodeType)
            {
              Hashtable myChildAttribs = new Hashtable();
    
              foreach (XmlAttribute childAttrib in child.Attributes)
              {
                if (XmlNodeType.Attribute == childAttrib.NodeType)
                  myChildAttribs.Add(childAttrib.Name, childAttrib.Value);
              }
              myConfigObject.Add(child.Name, myChildAttribs);
            }
          }
    
          return (myConfigObject);
        }
        #endregion
      }
    }
    

To add a custom section handler to an ASP.NET configuration file

  1. Add a sectionGroup and section element to your Web.config file inside the configSections element, as illustrated in the following code.

    Note

    Nesting a section element in a sectionGroup is optional, but is recommended to help organize configuration data.

    You can add the section handler declaration in a different configuration file than the one where you add your custom configuration elements providing that the configuration file where the section handler is declared is higher in the configuration file hierarchy. For more information, see ASP.NET Configuration File Hierarchy and Inheritance.

    The type attribute of the section element must match the manifest of the assembly or there will be a configuration error. The assembly file itself must be in the same ASP.NET application directory as the Web.config file that defines it.

    <configuration>
    
    <!-- Configuration section-handler declaration area. -->
      <configSections>
        <sectionGroup name="myCustomGroup">
          <section 
            name="myCustomSection" 
            type="MyConfigSectionHandler.MyHandler, MyCustomConfigurationHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 
            allowLocation="true" 
            allowDefinition="Everywhere"
          />
        </sectionGroup>
          <!-- Other <section> and <sectionGroup> elements. -->
      </configSections>
    
      <!-- Configuration section settings area. -->
    
    </configuration>
    
  2. Add your custom configuration elements in the configuration section settings area of your Web.config file.

    <configuration>
    
    <!-- Configuration section-handler declaration area. -->
    
      <!-- Configuration section settings area. -->
      <myCustomGroup>
        <myCustomSection myAttrib1="Clowns">
          <myChildSection 
              myChildAttrib1="Zippy" 
              myChildAttrib2="Michael Zawondy "/>
        </myCustomSection>
      </myCustomGroup>
    
      <!-- Other configuration settings, like <system.web> -->
    
    </configuration>
    

To programmatically access your custom configuration data

  • Obtain an instance of your custom configuration object and use the ConfigurationManager.GetSection method or the WebConfigurationManager.GetSection method to populate it.

    The following example of an ASPX page works with the previous examples to enumerate the attributes and child elements of the custom configuration section when a button is clicked.

    Because the custom section handler uses a Hashtable as the configuration object, the GetSection method returns a Hashtable.

    The following code goes in the .aspx page. The code for the button click event, which goes in the code-behind file, is contained in the next code example.

    The following code examples require the .NET Framework version 1.0 or 1.1.

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="BugTest.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
    
    <html>
      <head>
        <title>WebForm1</title>
        <meta name="GENERATOR" 
              Content="Microsoft Visual Studio .NET 2003">
        <meta name="CODE_LANGUAGE" Content="C#">
        <meta name=vs_defaultClientScript content="JavaScript">
        <meta name=vs_targetSchema 
              content="https://schemas.microsoft.com/intellisense/ie5">
      </head>
      <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post" runat="server">
        <h1>Enumerate MyCustomSection</h1>
        <asp:Label ID="Label1" runat="server" 
            Text="" />
        <br />
        <asp:Button ID="Button1" runat="server" 
            Text="Get Custom Config Info" 
            OnClick="Button1_Click" />
        </form>
      </body>
    </html>
    
    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
      <HEAD>
        <title>WebForm1</title>
        <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 2003">
        <meta name="CODE_LANGUAGE" Content="VB">
        <meta name="vs_defaultClientScript" content="JavaScript">
        <meta name="vs_targetSchema" content="https://schemas.microsoft.com/intellisense/ie5">
      </HEAD>
      <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post" runat="server">
          <h1>Enumerate MyCustomSection</h1>
          <asp:Label ID="Label1" runat="server" Text="" />
          <br>
          <asp:Button ID="Button1" runat="server" Text="Get Custom Config Info" OnClick="Button1_Click" />
        </form>
      </body>
    </HTML>
    

    The following code for the button click event goes in the code-behind file that belongs to the preceding .aspx page. The code-behind file uses the file name extension of .aspx.cs or .aspx.vb, depending on the language attribute of the @Page declaration.

    [C#]

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    using System.Configuration;
    using System.Text;
    
    namespace BugTest
    {
        /// <summary>
        /// Summary description for WebForm1.
        /// </summary>
        public class WebForm1 : System.Web.UI.Page
        {
            protected System.Web.UI.WebControls.Label Label1;
            protected System.Web.UI.WebControls.Button Button1;
    
            private void Page_Load(object sender, System.EventArgs e)
            {
                // Put user code to initialize the page here
            }
    
            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                //
                // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                //
                InitializeComponent();
                base.OnInit(e);
            }
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                this.Button1.Click += new System.EventHandler(this.Button1_Click);
                this.Load += new System.EventHandler(this.Page_Load);
    
            }
            #endregion
    
            protected void Button1_Click(object sender, System.EventArgs e)
            {
                Hashtable config = 
    (Hashtable)System.Configuration.ConfigurationSettings.GetConfig("myCustomGroup/myCustomSection");
    
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Config object item count = {0}<br/><br/>", config.Count);
                foreach (DictionaryEntry deKey in config)
                {
                    sb.AppendFormat("<h2>Attributes in the {0} Element:</h2>", 
                        deKey.Key.ToString());
                    Hashtable attribs = (Hashtable)deKey.Value;
                    foreach (DictionaryEntry deAttrib in attribs)
                    {
                        sb.AppendFormat("{0} = {1}<br/>", 
                            deAttrib.Key.ToString(), deAttrib.Value.ToString());
                    }
                }
                Label1.Text = sb.ToString();
                Label1.Visible = true;
    
            }
        }
    }
    
    Imports System.Text
    
    Public Class WebForm1
      Inherits System.Web.UI.Page
    
    #Region " Web Form Designer Generated Code "
    
      'This call is required by the Web Form Designer.
      <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    
      End Sub
      Protected WithEvents Label1 As System.Web.UI.WebControls.Label
      Protected WithEvents Button1 As System.Web.UI.WebControls.Button
    
      'NOTE: The following placeholder declaration is required by 
      ' the Web Form Designer.
      'Do not delete or move it.
      Private designerPlaceholderDeclaration As System.Object
    
      Private Sub Page_Init(ByVal sender As System.Object, ByVal _
    e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
      End Sub
    
    #End Region
    
      Private Sub Page_Load(ByVal sender As System.Object, ByVal _
    e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
      End Sub
    
      Protected Sub Button1_Click(ByVal sender As System.Object, ByVal _
    e As System.EventArgs) Handles Button1.Click
        Dim config As Hashtable = _
    System.Configuration.ConfigurationSettings.GetConfig( _
    "myCustomGroup/myCustomSection")
    
        Dim sb As New StringBuilder
        sb.AppendFormat("Config object item count = {0}<br/><br/>", _
    config.Count)
    
        For Each deKey As DictionaryEntry In config
          sb.AppendFormat("<h2>Attributes in the {0} Element:</h2>", _
    deKey.Key.ToString())
          Dim attribs As Hashtable = deKey.Value
          For Each deAttrib As DictionaryEntry In attribs
            sb.AppendFormat("{0} = {1}<br/>", deAttrib.Key.ToString(), _
    deAttrib.Value.ToString())
          Next
          Label1.Text = sb.ToString()
          Label1.Visible = True
        Next
    
      End Sub
    End Class
    

See Also

Tasks

How to: Create Custom Configuration Sections Using ConfigurationSection

Concepts

ASP.NET Configuration File Structure (Sections and Section Handlers)

Other Resources

ASP.NET Web Site Administration

ASP.NET Web Site Administration

Configuring .NET Framework Apps