Create the Configuration Section Handler and Its Components
These steps demonstrate how to create the configuration section handler and its components. So that you can better maintain and reuse the code, these steps demonstrate how to create a class named ConfigHelper that includes static methods. These static methods help you parse and retrieve the XML attributes in the configuration file. Because the code to build ConfigHelper uses an enumeration and a string in the configuration section, ConfigHelper contains two methods, GetEnumValue and GetStringValue.The GetEnumValue method parses the configuration section for an attribute with predefined values, verifies that the value of the attribute is valid, and then returns the attribute and its value. The GetStringValue method parses the configuration section for an attribute and then returns the attribute and its value.
- Start Microsoft Visual Studio .NET.
- On the File menu, point to New, and then click Project.
- In the New Project dialog box, click Visual C# Projects under Project Types, and then click Class Library under Templates. In the Name text box, type MyConfig, and then click OK.
- Add a reference to the System.Web.dll assembly.
- Rename Class1.cs as MyConfig.cs.
- From Solution Explorer, open MyConfig.cs.
- Add the following namespace declarations to the top of the file:
using System.Configuration; using System.Web; using System.Xml;
- Delete the default class definition.
- Add an enumeration to hold an attribute for the custom configuration section:
public enum LevelSetting { High, Medium, Low, None }
- Create a class named MyConfigSection to hold the configuration information. This class is the object that the Create method implementation returns.
public class MyConfigSection { private LevelSetting level = LevelSetting.None; private string name = ""; public MyConfigSection(LevelSetting _level, string _name) { level = _level; name = _name; } public LevelSetting Level { get {return level;} } public string Name { get {return name;} } }
- Create a class named ConfigHelper as follows:
NOTE: You can also create a helper method for each data type for which you use your configuration section (for example, GetIntValue and GetBooleanValue).
internal class ConfigHelper { //Helper method for retrieving enum values from XmlNode. public static XmlNode GetEnumValue (XmlNode _node, string _attribute,Type _enumType, ref int _val) { XmlNode a = _node.Attributes.RemoveNamedItem(_attribute); if(a==null) throw new ConfigurationException("Attribute required: " + _attribute); if(Enum.IsDefined(_enumType, a.Value)) _val = (int)Enum.Parse(_enumType,a.Value); else throw new ConfigurationException("Invalid Level: '" + a.Value + "'",a); return a; } //Helper method for retrieving string values from xmlnode. public static XmlNode GetStringValue(XmlNode _node, string _attribute, ref string _val) { XmlNode a = _node.Attributes.RemoveNamedItem(_attribute); if(a==null) throw new ConfigurationException("Attribute required: " + _attribute); else _val = a.Value; return a; } }
- Create a class named MyConfigSectionHandler. This class inherits the IConfigurationSectionHandler interface and implements the Create method of that interface. In the Create method, this code uses the ConfigHelper class to retrieve the values from the configuration file. The sample then creates and returns the MyConfigSection object.
The MyConfigSectionHandler class should appear as follows:public class MyConfigSectionHandler : IConfigurationSectionHandler { public virtual object Create(object parent,object configContext,XmlNode section) { int iLevel = 0; string sName = ""; ConfigHelper.GetEnumValue(section, "level", typeof(LevelSetting), ref iLevel); ConfigHelper.GetStringValue(section, "name", ref sName); return new MyConfigSection((LevelSetting)iLevel,sName); } }
- Save and compile the project.
Complete Code Listing
In its final form, your class file should appear as follows:
using System;
using System.Web;
using System.Xml;
using System.Configuration;
namespace MyConfig
{
public enum LevelSetting
{
High,
Medium,
Low,
None
}
public class MyConfigSectionHandler : IConfigurationSectionHandler
{
public virtual object Create(object parent,object configContext,XmlNode section)
{
int iLevel = 0;
string sName = "";
ConfigHelper.GetEnumValue(section, "level", typeof(LevelSetting), ref iLevel);
ConfigHelper.GetStringValue(section,"name",ref sName);
return new MyConfigSection((LevelSetting)iLevel,sName);
}
}
public class MyConfigSection
{
private LevelSetting level = LevelSetting.None;
private string name = null;
public MyConfigSection(LevelSetting _level,string _name)
{
level = _level;
name = _name;
}
public LevelSetting Level
{
get {return level;}
}
public string Name
{
get {return name;}
}
}
internal class ConfigHelper
{
public static XmlNode GetEnumValue
(XmlNode _node, string _attribute,Type _enumType, ref int _val)
{
XmlNode a = _node.Attributes.RemoveNamedItem(_attribute);
if(a==null)
throw new ConfigurationException("Attribute required: " + _attribute);
if(Enum.IsDefined(_enumType, a.Value))
_val = (int)Enum.Parse(_enumType,a.Value);
else
throw new ConfigurationException("Invalid Level",a);
return a;
}
public static XmlNode GetStringValue(XmlNode _node, string _attribute, ref string _val)
{
XmlNode a = _node.Attributes.RemoveNamedItem(_attribute);
if(a==null)
throw new ConfigurationException("Attribute required: " + _attribute);
else
_val = a.Value;
return a;
}
}
}
Test the Configuration Handler
- Open Visual Studio .NET.
- In the New Project dialog box, click Visual C# Projects under Project Types, and click ASP.NET Web Application under Templates. Specify the name and location for your new project.
- Add a reference to MyConfig.dll.
- Open the Web.config file. Add the following code within the <configuration> section:
<configSections> <sectionGroup name="system.web"> <section name="myConfig" type="MyConfig.MyConfigSectionHandler,MyConfig" /> </sectionGroup> </configSections>
- Add the following code within the <system.web> section:
<myConfig level="High" name="hello world" />
- Open the code-behind file for WebForm1.aspx, which is named WebForm1.aspx.cs by default. Add the following namespace declaration to the top of WebForm1.aspx.cs:
using MyConfig;
- Add the following code to the Page_Load event. This code calls the GetConfig method to retrieve an instance of the MyConfigSection object and then writes out the values of the two properties of the object.
MyConfigSection s = (MyConfigSection)Context.GetConfig("system.web/myConfig"); Response.Write("Level: " + s.Level + "<br>"); Response.Write("Name: " + s.Name);
- Save and compile the application.
- View the page in the browser. The following output should appear:Level: High
Name: hello world
Troubleshooting
When you create a custom ASP.NET configuration section handler, use the following guidelines when you implement the IConfigurationSectionHandler interface:- Instances of your class that implement the IConfigurationSectionHandler interface must be thread-safe and stateless. You must be able to call the IConfigurationSectionHandler.Create method from multiple threads simultaneously.
- The configuration object that IConfigurationSectionHandler.Create returns must be thread-safe and immutable.
- Do not modify the parent argument to IConfigurationSectionHandler.Create. Because the configuration system caches the configuration objects, it is important that you not modify the parent argument to IConfigurationSectionHandler.Create. For example, if the return value of IConfigurationSectionHandler.Create is only a small modification of the parent, you must modify a clone of the parent, not the original.