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
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 } }
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
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>
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
Administering ASP.NET Web Sites