Sunday, 3 February 2013

Create Custom Configuration Sections Using IConfigurationSectionHandler

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.
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.

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.

    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 System.Configuration.ConfigurationManager.GetSection(System.String) method or the System.Web.Configuration.WebConfigurationManager.GetSection(System.String) 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.
    C#

    <%@ 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="http://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>

    VB

    <%@ 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="http://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;

            }
        }
    }

    VB

    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

No comments:

Post a Comment

Note: only a member of this blog may post a comment.