Article ID: 318457
Article Last Modified on 6/17/2003
APPLIES TO
- Microsoft ASP.NET 1.0
- Microsoft Visual Basic .NET 2002 Standard Edition
- Microsoft ASP.NET 1.1
- Microsoft Visual Basic .NET 2003 Standard Edition
This article was previously published under Q318457
For a Microsoft Visual C# .NET version of this article, see 309045.
This article refers to the following Microsoft .NET Framework Class Library namespaces:
- System.Configuration
- System.Enum
- System.Xml
IN THIS TASK
SUMMARY
This article describes how to use Visual Basic .NET to create a custom configuration section handler for ASP.NET.
back to the top
Create the Configuration Section Handler and Its Components
These steps demonstrate how to create the configuration section handler and its components. These steps demonstrate how to create a class that is named ConfigHelper that includes static methods, so that you can better maintain and reuse the code. These static methods help you to parse and to retrieve the XML attributes in the configuration file. Because the code to build the ConfigHelper class uses an enumeration and a string in the configuration section, the ConfigHelper class contains two methods that are named 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 Basic Projects under Project Types, and then click Class Library under Templates.
- In the Name box, type MyConfig, and then click OK.
- Add a reference to the System.Web.dll assembly.
- Rename Class1.vb to MyConfig.vb.
- In Solution Explorer, open MyConfig.vb.
Add the following namespace declarations to the top of the file:
Imports System.Configuration Imports System.Web Imports System.Xml Imports System.Enum
- Delete the default class definition.
Create a namespace that is named MyConfig:
Namespace MyConfig ' Code in the remaining steps will go in this namespace block. End Namespace
Add an enumeration to hold an attribute for the custom configuration section:
Public Enum LevelSetting High = 3 Medium = 2 Low = 1 None = 0 End Enum
Create a class that is named MyConfigSection to hold the configuration information. This class is the object that the Create method implementation returns:
Public Class MyConfigSection Private mylevel As LevelSetting = LevelSetting.None Private myname As String = "" Public Sub New(ByVal configLevel As LevelSetting, ByVal configName As String) mylevel = configLevel myname = configName End Sub Public ReadOnly Property Level() As LevelSetting Get Return mylevel End Get End Property Public ReadOnly Property Name() As String Get Return myname End Get End Property End Class
Create a class that is named ConfigHelper:
Friend Class ConfigHelper Public Shared Function GetEnumValue(ByVal node As XmlNode, _ ByVal attribute As String, _ ByVal enumType As Type, _ ByRef val As Integer) As XmlNode Dim a As XmlNode = node.Attributes.RemoveNamedItem(attribute) If (a Is Nothing) Then Throw New ConfigurationException("Attribute required: " + attribute) End If If IsDefined(enumType, a.Value) Then val = CType(Parse(enumType, a.Value), Integer) Else Throw New ConfigurationException("Invalid Level: '" + a.Value + "'", a) End If Return a End Function Public Shared Sub GetStringValue(ByVal node As XmlNode, _ ByVal attribute As String, _ ByRef val As String) Dim a As XmlNode = node.Attributes.RemoveNamedItem(attribute) If (a Is Nothing) Then Throw New ConfigurationException("Attribute required: " + attribute) Else val = a.Value End If End Sub End Class
NOTE: You can also create a helper method for each data type for which you use your configuration section (for example, GetIntValue and GetBooleanValue).
Create a class that is 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 is:
Public Class MyConfigSectionHandler Implements IConfigurationSectionHandler Friend Function Create(ByVal parent As Object, _ ByVal configContext As Object, _ ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create Dim configLevel As Integer = 0 Dim configName As String = "" Dim l As LevelSetting ConfigHelper.GetEnumValue(section, "level", l.GetType(), configLevel) ConfigHelper.GetStringValue(section, "name", configName) Return New MyConfigSection(CType(configLevel, LevelSetting), configName) End Function End Class
- Save and then compile the project.
Complete Code Listing
In its final form, your class file is:
Imports System Imports System.Web Imports System.Xml Imports System.Configuration Imports System.Enum Namespace MyConfig Public Enum LevelSetting High = 3 Medium = 2 Low = 1 None = 0 End Enum Public Class MyConfigSectionHandler Implements IConfigurationSectionHandler Friend Function Create(ByVal parent As Object, _ ByVal configContext As Object, _ ByVal section As XmlNode) As Object _ Implements IConfigurationSectionHandler.Create Dim configLevel As Integer = 0 Dim configName As String = "" Dim l As LevelSetting ConfigHelper.GetEnumValue(section, "level", l.GetType(), configLevel) ConfigHelper.GetStringValue(section, "name", configName) Return New MyConfigSection(CType(configLevel, LevelSetting), configName) End Function End Class Public Class MyConfigSection Private mylevel As LevelSetting = LevelSetting.None Private myname As String = "" Public Sub New(ByVal configLevel As LevelSetting, _ ByVal configName As String) mylevel = configLevel myname = configName End Sub Public ReadOnly Property Level() As LevelSetting Get Return mylevel End Get End Property Public ReadOnly Property Name() As String Get Return myname End Get End Property End Class Friend Class ConfigHelper Public Shared Function GetEnumValue(ByVal node As XmlNode, _ ByVal attribute As String, _ ByVal enumType As Type, _ ByRef val As Integer) As XmlNode Dim a As XmlNode = node.Attributes.RemoveNamedItem(attribute) If (a Is Nothing) Then Throw New ConfigurationException("Attribute required: " + attribute) End If If IsDefined(enumType, a.Value) Then val = CType(Parse(enumType, a.Value), Integer) Else Throw New ConfigurationException("Invalid Level: '" + a.Value + "'", a) End If Return a End Function Public Shared Sub GetStringValue(ByVal node As XmlNode, _ ByVal attribute As String, _ ByRef val As String) Dim a As XmlNode = node.Attributes.RemoveNamedItem(attribute) If (a Is Nothing) Then Throw New ConfigurationException("Attribute required: " + attribute) Else val = a.Value End If End Sub End Class End Namespace
Test the Configuration Section Handler
- Start Visual Studio .NET.
- In the Add New Project dialog box, click Visual Basic Projects under Project Types, and then 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 in the <configuration> section:
<configSections> <sectionGroup name="system.web"> <section name="myConfig" type="MyConfig.MyConfigSectionHandler,MyConfig" /> </sectionGroup> </configSections>
Add the following code in the <system.web> section:
<myConfig level="High" name="hello world" />
Open the code-behind file for WebForm1.aspx. By default, this is named WebForm1.aspx.vb. Add the following namespace declaration to the top of WebForm1.aspx.vb:
Imports 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 the values of the two properties of the object:
Dim s As MyConfigSection = CType( _ Context.GetConfig("system.web/myConfig"), _ MyConfigSection) Response.Write("Level: " + s.Level.ToString + "<br>") Response.Write("Name: " + s.Name)
- Save and then compile the program.
- View the page in the browser. The following output appears:
Level: High
Name: hello world
Troubleshooting
Use the following guidelines to implement the IConfigurationSectionHandler interface when you create a custom ASP.NET configuration section handler:
- 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 the IConfigurationSectionHandler.Create method returns must be thread-safe and immutable.
- Do not modify the parent argument to the IConfigurationSectionHandler.Create method. Because the configuration system caches the configuration objects, it is important not to modify the parent argument to the IConfigurationSectionHandler.Create method. For example, if the return value of the IConfigurationSectionHandler.Create method is only a small modification of the parent, you must modify a clone of the parent, not the original.
REFERENCES
For additional information about ASP.NET configuration, click the article number below to view the article in the Microsoft Knowledge Base:
307626 INFO: ASP.NET Configuration Overview
307513 PRB: Access Violation Occurs When You Use a Custom Configuration Section Handler in an ASP.NET Application That Is Under Stress
Keywords: kbhowtomaster kbweb kbconfig KB318457