This article describes how to use Visual Basic .NET to create a custom configuration section handler for ASP.NET.
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:
- 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.