Recipe 12.7. Adding Your Own Configuration Elements to web.config


Problem

You want to create and add your own configuration elements to web.config. No predefined element will do, nor will use of the <appSettings> key/value entries of web.config, as described in Recipe 12.2.

Solution

Determine what configuration information you want to store in web.config, create your own custom section handler for parsing the element, add the definition of the section handler to web.config, add the new configuration element to web.config, and use the configuration information in your application.

  1. Determine what configuration information you want to store in web.config.

  2. Use the .NET language of your choice to create a custom section handler class for parsing your newly defined element.

  3. Add the definition of the section handler to the <configSections> section of web.config.

  4. Add the configuration element to web.config and assign values to its attributes or child elements.

  5. In the code-behind class for your ASP.NET page, use the .NET language of your choice to access and put the custom configuration data to work.

The code we've written to illustrate this solution appears in Examples 12-9, 12-10, 12-11, 12-12, 12-13 through 12-14. Examples 12-9 (VB) and 12-10 (C#) show the class for a custom section handler. The changes we've made to web.config to have it use the custom section handler are shown in Example 12-11. Example 12-12 shows the .aspx file for a sample web form that displays some custom configuration settings. Examples 12-13 and 12-14 show the code-behind class that accesses the custom configuration information. The output of the sample web form showing the data read using the custom configuration handler is shown in Figure 12-3.

Figure 12-3. Configuration information read by configuration handler


Discussion

Sometimes the predefined configuration elements provided by ASP.NET, including the key/value collection available through the <appSettings> element of web.config (described in Recipe 12.2), are not enough. When this is the case, being able to store any configuration information required by your application in its own custom section in web.config can be a useful alternative. What's more, having a custom section in web.config can be a real boon to program clarity and ease of implementation.

As a prelude to discussing the custom section for web.config, it's worthwhile reviewing the basic structure of a machine.config file, as shown next, because it is the machine.config file whose structure we will mimic. The root node of the XML document is <configuration>. The <configSections> child element is next. It defines the configuration section elements that will follow and the configuration handlers (classes) that will handle the configuration information contained in the elements. When <configSections> is present, it must be the first child element of <configuration>.

 <?xml version="1.0" encoding="UTF-8"?> <configuration> <configSections> … </configSections> <!-- sections defined in configSections --> </configuration> 

Even if you are used to looking at a web.config file, you have probably never seen the <configSections> element. This is because all of the standard configuration handlers are defined in machine.config. (ASP.NET reads the machine.config file and then the web.config file(s) for your application. All of the data from the machine.config file is used unless a section in web.config overrides the equivalent section in machine.config.) Because <configSections> is only used to define configuration handlers, it never appears in a web.config file unless your application uses custom configuration handlers like the one described in this example.

In this example, we use a <siteProperties> custom element to hold the information we want to store in web.config and that will be used by our custom configuration handler. We have chosen the path of using a custom element (and a custom configuration handler) because of the flexibility it affords us and the clarity with which we can express the information to be stored.

In creating your own custom element, you first need to determine the configuration information you want to store in web.config and then define the format you want it stored in. The only limitation is that the data element must be a well-formed XML node. You can use attributes, child elements, or any combination of the two to hold your custom configuration information. In our example, we use attributes only. The well-formed XML that defines the section we want to add to our application web.config is shown here:

 <siteProperties applicationName="ASP.NET Cookbook"    databaseServer="192.168.0.1"    databaseName="ASPNetCookbook_DB"    databaseUserName="aspnetcookbook"    databaseUserPassword="efficient"       emailServer="mail@mailservices.com" /> 

The section can be named anything you like as long as it does not conflict with any predefined ASP.NET elements. We recommend that, for consistency, you stick with the mixed-case convention used by ASP. NET. Section names and attributes are case-sensitive.


After defining your configuration element and specifying the values of the information it will store, create a custom configuration handler in a separate project. This way, the created assembly can be reused easily in multiple applications. For our example, the project was named VBCustomConfigHandlers (CSCustomConfigHandlers for C#), which by default will generate an assembly with the same name.

In your configuration handler project, add a new class named to reflect the configuration element the handler supports. In our example, we've named the class SiteConfigHandlerVB (SiteConfigHandlerCS for C#) because the section added to web.config contains site configuration information.

To act as a custom configuration handler, the class must implement the IConfigurationSectionHandler interface:

 

Namespace VBCustomConfigHandlers Public Class SiteConfigHandlerVB Implements IConfigurationSectionHandler

… End Class SiteConfigHandlerVB End Namespace 'VBCustomConfigHandlers

namespace CSCustomConfigHandlers { public class SiteConfigHandlerCS : IConfigurationSectionHandler { … } // SiteConfigHandlerCS } // CSCustomConfigHandlers

The IConfigurationSectionHandler interface requires that you implement a single method, Create, which requires three parameters: parent, configContext, and section. The parent parameter provides a reference to the corresponding parent configuration section, and the configContext parameter provides a reference to the current ASP.NET context. Neither is used in this example. The section parameter provides a reference to the XML node (section) of the web.config file that is to be processed. In our example, section will be set to reference the <siteProperties> section added to web.config.

 

Namespace VBCustomConfigHandlers Public Class VBSiteConfigHandler Implements IConfigurationSectionHandler Public Function Create(ByVal parent As Object, _ ByVal configContext As Object, _ ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create … End Function 'Create End Class 'VBSiteConfigHandler End Namespace 'VBCustomConfigHandlers

namespace CSCustomConfigHandlers { public class CSSiteConfigHandler : IConfigurationSectionHandler { public Object Create(Object parent, Object configContext, XmlNode section) { … } // Create } // CSSiteConfigHandler } // CSCustomConfigHandlers

The Create method returns an object that contains the configuration information from the passed section. This can be anything you want it to be. The most flexible approach is to define a class that will contain the data and provide easy access by your application. In our example, the returned class is defined in the same file as the SiteConfigHandlerVB (SiteConfigHandlerCS for C#) class.

 

Namespace VBCustomConfigHandlers Public Class VBSiteConfigHandler Implements IConfigurationSectionHandler Public Function Create(ByVal parent As Object, _ ByVal configContext As Object, _ ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create … End Function 'Create End Class 'VBSiteConfigHandler 'The following class provides the container returned by 'the SiteConfigHandlerVB Public Class SiteConfigurationVB … End Class 'SiteConfigurationVB End Namespace 'VBCustomConfigHandlers

namespace CSCustomConfigHandlers { public class CSSiteConfigHandler : IConfigurationSectionHandler { public Object Create(Object parent, Object configContext, XmlNode section) { … } // Create } // CSSiteConfigHandler // The following class provides the container returned by // the SiteConfigHandlerCS public class SiteConfigurationCS { … } // SiteConfigurationCS } // CSCustomConfigHandlers

The SiteConfigurationVB (SiteConfigurationCS for C#) class needs a constructor that has parameters for each of the configuration items and a read-only property for each of the configuration items. The code for our example is shown in Examples 12-9 (VB) and 12-10 (C#).

After the class that will be used for the return is defined, the Create method should extract the configuration information from the passed XML section, create a new instance of the SiteConfigurationVB (SiteConfigurationCS for C#) object, and return a reference to the new instance. For our example, attributes were used for the configuration information in the section. This allows us to get a reference to the attributes collection of the section and to extract the individual values by using the GetNamedItem method of the attributes collection.

 

Public Function Create(ByVal parent As Object, _ ByVal configContext As Object, _ ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create Dim siteConfig As SiteConfigurationVB Dim attributes As XmlAttributeCollection attributes = section.Attributes With attributes siteConfig = _ New SiteConfigurationVB(.GetNamedItem("applicationName").Value, _ .GetNamedItem("databaseServer").Value, _ .GetNamedItem("databaseName").Value, _ .GetNamedItem("databaseUserName").Value, _ .GetNamedItem("databaseUserPassword").Value, _ .GetNamedItem("emailServer").Value) End With 'attributes Return (siteConfig) End Function 'Create

public Object Create(Object parent, Object configContext, XmlNode section) { SiteConfigurationCS siteConfig = null; XmlAttributeCollection attributes = null; attributes = section.Attributes; siteConfig = new SiteConfigurationCS( attributes.GetNamedItem("applicationName").Value, attributes.GetNamedItem("databaseServer").Value, attributes.GetNamedItem("databaseName").Value, attributes.GetNamedItem("databaseUserName").Value, attributes.GetNamedItem("databaseUserPassword").Value, attributes.GetNamedItem("emailServer").Value); return (siteConfig); } // Create

With the customconfiguration handler, you need to add the handler information to web.config to tell ASP.NET how to handle the <siteProperties> section you've added. Add a <configSections> element at the top of your web.config that contains a single section element. The name attribute defines the name of the custom section containing your configuration information. The type attribute defines the class and assembly name in the form type="class, assembly" that will process your custom configuration section. The class name must be a fully qualified class name. The assembly name must be the name of the assembly (dll) created in your configuration handler project, described earlier.

  <configSections> <section name="siteProperties" type="ASPNetCookbook.VBCustomConfigHandlers.SiteConfigHandlerVB,   VbCustomConfigHandlers" />  </configSections> 

When the <configSections> element is present, it must be the first element in the web.config file after the <configuration> element or a parsing exception will be thrown.


The last thing you need to do before you can use the custom configuration in your application is to add a reference to the VBCustomConfigHandlers (CSCustomConfigHandlers for C#) assembly in your application.

Accessing the custom configuration information in your application requires using ConfigurationManager.GetConfig and passing it the name of your custom section. This method returns an object that must be cast to the object type you returned in your custom configuration handler class. After the reference is obtained, all of the site information is available as properties of the object.

 

Dim siteConfig As SiteConfigurationVB siteConfig = CType(ConfigurationManager.GetSection("siteProperties"), _ SiteConfigurationVB) labApplicationName.Text = siteConfig.applicationName labDBServer.Text = siteConfig.databaseServer labDBName.Text = siteConfig.databaseName labDBUserName.Text = siteConfig.databaseUserName labDBUserPassword.Text = siteConfig.databaseUserPassword labEmailServer.Text = siteConfig.emailServer

SiteConfigurationCS siteConfig = null; siteConfig = (SiteConfigurationCS) (ConfigurationManager.GetSection("siteProperties")); labApplicationName.Text = siteConfig.applicationName; labDBServer.Text = siteConfig.databaseServer; labDBName.Text = siteConfig.databaseName; labDBUserName.Text = siteConfig.databaseUserName; labDBUserPassword.Text = siteConfig.databaseUserPassword; labEmailServer.Text = siteConfig.emailServer;

See Also

Recipe 12.2

Example 12-9. Custom section handler class (.vb)

 Option Explicit On Option Strict On Imports System Imports System.Configuration Imports System.Xml Namespace ASPNetCookbook.VBCustomConfigHandlers  ''' <summary>  ''' This class provides a custom site configuration handler.  ''' </summary>  Public Class SiteConfigHandlerVB Implements IConfigurationSectionHandler '''***********************************************************************     ''' <summary> ''' This routine provides the creation of the SiteConfigurationVB object ''' from the passed section of the web.config file ''' </summary> ''' ''' <param name="parent">Set to the parent of this section</param> ''' <param name="configContext">Set the HttpContext of the current ''' request ''' </param> ''' <param name="section">Set to the XML node containing the ''' configuration data to be used to create this object ''' </param> ''' <returns>SiteConfigHandlerVB initialied from the passed section ''' of the web.config file ''' </returns> Public Function Create(ByVal parent As Object, _               ByVal configContext As Object, _   ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create   Dim siteConfig As SiteConfigurationVB Dim attributes As XmlAttributeCollection attributes = section.Attributes With attributes    siteConfig = _ New SiteConfigurationVB(.GetNamedItem("applicationName").Value, _ .GetNamedItem("databaseServer").Value, _ .GetNamedItem("databaseName").Value, _  .GetNamedItem("databaseUserName").Value, _ .GetNamedItem("databaseUserPassword").Value, _ .GetNamedItem("emailServer").Value)    End With 'attributes    Return (siteConfig)   End Function 'Create  End Class 'SiteConfigHandlerVB    'The following class provides the container returned by  'the SiteConfigHandlerVB  Public Class SiteConfigurationVB Private mApplicationName As String Private mDatabaseServer As String Private mDatabaseName As String Private mDatabaseUserName As String Private mDatabaseUserPassword As String Private mEmailServer As String Public ReadOnly Property applicationName() As String Get Return (mApplicationName) End Get End Property 'applicationName     Public ReadOnly Property databaseServer() As String Get Return (mDatabaseServer) End Get End Property 'databaseServer     Public ReadOnly Property databaseName() As String Get Return (mDatabaseName) End Get End Property 'databaseName Public ReadOnly Property databaseUserName() As String Get Return (mDatabaseUserName) End Get End Property 'databaseUserName     Public ReadOnly Property databaseUserPassword() As String Get Return (mDatabaseUserPassword) End Get End Property 'databaseUserPassword     Public ReadOnly Property emailServer() As String Get Return (mEmailServer) End Get End Property 'emailServer    '''***********************************************************************    ''' <summary>    ''' This constructor creates the object and populates the attributes    ''' with the passed values    ''' </summary>    Public Sub New(ByVal applicationName As String, _   ByVal databaseServer As String, _   ByVal databaseName As String, _   ByVal databaseUserName As String, _   ByVal databaseUserPassword As String, _   ByVal emailServer As String)     mApplicationName = applicationName mDatabaseServer = databaseServer mDatabaseName = databaseName mDatabaseUserName = databaseUserName mDatabaseUserPassword = databaseUserPassword mEmailServer = emailServer   End Sub 'New End Class 'SiteConfigurationVB End Namespace 

Example 12-10. Custom section handler class (.cs)

 using System; using System.Configuration; using System.Xml; namespace ASPNetCookbook.CSCustomConfigHandlers {  /// <summary>  /// This class provides a custom site configuration handler.  /// </summary>  public class SiteConfigHandlerCS : IConfigurationSectionHandler  { ///*********************************************************************** /// <summary> /// This routine provides the creation of the SiteConfigurationVB object /// from the passed section of the web.config file /// </summary> /// /// <param name="parent">Set to the parent of this section</param> /// <param name="configContext">Set the HttpContext of the current /// request /// </param> /// <param name="section">Set to the XML node containing the /// configuration data to be used to create this object /// </param> /// <returns>SiteConfigHandlerVB initialied from the passed section /// of the web.config file /// </returns> public Object Create(Object parent, Object configContext, XmlNode section) { SiteConfigurationCS siteConfig = null; XmlAttributeCollection attributes = null; attributes = section.Attributes; siteConfig = new SiteConfigurationCS( attributes.GetNamedItem("applicationName").Value, attributes.GetNamedItem("databaseServer").Value, attributes.GetNamedItem("databaseName").Value, attributes.GetNamedItem("databaseUserName").Value, attributes.GetNamedItem("databaseUserPassword").Value, attributes.GetNamedItem("emailServer").Value); return (siteConfig); } // Create } // SiteConfigHandlerCS // The following class provides the container returned by // the SiteConfigHandlerCS public class SiteConfigurationCS { private String mApplicationName = null; private String mDatabaseServer = null; private String mDatabaseName = null; private String mDatabaseUserName = null; private String mDatabaseUserPassword = null; private String mEmailServer = null; public String applicationName { get { return (mApplicationName); } } // applicationName public String databaseServer { get { return (mDatabaseServer); } } // databaseServer public String databaseName { get { return (mDatabaseName); } } // databaseName public String databaseUserName { get { return (mDatabaseUserName); } } // databaseUserName public String databaseUserPassword { get { return (mDatabaseUserPassword); } } // databaseUserPassword public String emailServer { get { return (mEmailServer); } } // emailServer //************************************************************************ // //   ROUTINE: Constructor // //   DESCRIPTION: This constructor creates the object and populates the //   attributes with the passed values //------------------------------------------------------------------------ public SiteConfigurationCS(String applicationName,    String databaseServer,    String databaseName,    String databaseUserName,    String databaseUserPassword,    String emailServer) { mApplicationName = applicationName; mDatabaseServer = databaseServer; mDatabaseName = databaseName; mDatabaseUserName = databaseUserName; mDatabaseUserPassword = databaseUserPassword; mEmailServer = emailServer; } // SiteConfigurationCS   } // SiteConfigurationCS } 

Example 12-11. Changes to web.config to use the custom section handler

 <?xml version="1.0"?> <configuration> <configSections>  <section name="siteProperties" type="ASPNetCookbook.VBCustomConfigHandlers.SiteConfigHandlerVB,   VBCustomConfigHandlers" /> </configSections> <system.web> … </system.web> <!-- Setting for custom configuration section handler in chapter 12  --> <siteProperties applicationName="ASP.NET Cookbook" databaseServer="192.168.0.1" databaseName="ASPNetCookbook_DB" databaseUserName="aspnetcookbook" databaseUserPassword="efficient" emailServer="mail@mailservices.com" /> </configuration> 

Example 12-12. Sample web form using custom configuration data (.aspx)

 <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"  AutoEventWireup="false"  CodeFile="CH12CustomConfigHandlerVB.aspx.vb"  Inherits="ASPNetCookbook.VBExamples.CH12CustomConfigHandlerVB"  Title="Custom Config Handler" %> <asp:Content  runat="server" ContentPlaceHolder>  <div align="center" >     Writing Custom Configuration Handlers (VB)  </div>  <table width="60%" align="center" border="0">      <tr>   <td align="right" width="50%" > applicationName = </td>   <td width="50%" >      <asp:Label  runat="server" />   </td> </tr> <tr>   <td align="right" > databaseServer = </td>   <td > <asp:Label  runat="server" />   </td> </tr> <tr>   <td align="right" >     databaseName = </td>   <td > <asp:Label  runat="server" />   </td> </tr> <tr>    <td align="right" >   databaseUserName = </td>    <td >   <asp:Label  runat="server" />    </td> </tr> <tr>    <td align="right" >       databaseUserPassword = </td>    <td >   <asp:Label  runat="server" />   </td> </tr>     <tr>    <td align="right" >       emailServer = </td>    <td >       <asp:Label  runat="server" />    </td> </tr> </table> </asp:Content> 

Example 12-13. Sample web form using custom configuration data code-behind (.vb)

 Option Explicit On Option Strict On Imports ASPNetCookbook.VBCustomConfigHandlers Imports System Imports System.Configuration Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH12CustomConfigHandlerVB.aspx ''' </summary> Partial Class CH12CustomConfigHandlerVB Inherits System.Web.UI.Page '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Private Sub Page_Load(ByVal sender As Object, _       ByVal e As System.EventArgs) Handles Me.Load   Dim siteConfig As SiteConfigurationVB      siteConfig = CType(ConfigurationManager.GetSection("siteProperties"), _  SiteConfigurationVB)   labApplicationName.Text = siteConfig.applicationName   labDBServer.Text = siteConfig.databaseServer   labDBName.Text = siteConfig.databaseName   labDBUserName.Text = siteConfig.databaseUserName   labDBUserPassword.Text = siteConfig.databaseUserPassword   labEmailServer.Text = siteConfig.emailServer End Sub 'Page_Load End Class 'CH12CustomConfigHandlerVB End Namespace 

Example 12-14. Sample web form using custom configuration data code-behind (.cs)

 using ASPNetCookbook.CSCustomConfigHandlers; using System; using System.Configuration; using System.Web.Configuration; namespace ASPNetCookbook.CSExamples {  /// <summary>  /// This class provides the code behind for  /// CH12CustomConfigHandlerCS.aspx  /// </summary>  public partial class CH12CustomConfigHandlerCS : System.Web.UI.Page  { ///*********************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void Page_Load(object sender, EventArgs e) { SiteConfigurationCS siteConfig = null; siteConfig = (SiteConfigurationCS)  (ConfigurationManager.GetSection("siteProperties")); labApplicationName.Text = siteConfig.applicationName; labDBServer.Text = siteConfig.databaseServer; labDBName.Text = siteConfig.databaseName; labDBUserName.Text = siteConfig.databaseUserName; labDBUserPassword.Text = siteConfig.databaseUserPassword; labEmailServer.Text = siteConfig.emailServer; } // Page_Load } // CH12CustomConfigHandlerCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2003
Pages: 202

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net