ASP.NET

Einblick in Custom Configuration Sections

Benutzerdefinierte Konfigurationsabschnitte in der web.config

Für einen Response-Filter, der den HTML-Code vor der Ausgabe noch einmal gezielt verändern kann, habe ich eine Lösung gesucht, die dafür notwendigen Informationen zentral abzulegen. Nahe liegend ist da natürlich die Verwendung der ASP.NET-eigenen web.config. In diesem Fall genügten mir aber die einfachen Key/Value-Paarungen des Abschnittes AppSettings nicht, da ich mindestens 4 Konfigurationswerte unterbringen wollte, und dies auch noch mehrfach:

  • pageName
  • findString
  • newString
  • type

Die Lösung liegt in der Verwendung der Klasse ConfigurationSection, mit der man relativ einfach eigene Konfigurationsabschnittstypen implementieren kann. In einer Klasse, die von ConfigurationSection ableitet, werden im Grunde die einzelnen Eigenschaften (Properties) definiert, die später in der web.config konfigurierbar sind und per Code über den ConfigurationManager abrufbar werden.

Einfaches Konfigurationselement

Fangen wir mit dem Wurzelelement an, das zusätzlich ein Attribut namens active erhalten soll, mit dem man später den ResponseFilter einfach ein- und ausschalten kann:

'*** Definition des Konfigurationsabschnitts
Public Class ResponseFilterConfiguration
    Inherits ConfigurationSection

    <ConfigurationProperty("active", DefaultValue:="True", IsRequired:=True)> _
    Public ReadOnly Property Active() As Boolean
        Get
            Return CType(MyBase.Item("active"), Boolean)
        End Get
    End Property

End Class

Jedes ConfigurationProperty besitzt unter anderem folgende wichtige Attribute:

AttributBeschreibung
NameName der Eigenschaft (erforderlich)
DefaultValueStandardwert der Eigenschaft
IsRequiredIst das Element erforderlich?
IsKeyIst der Inhalt des Element ein eindeutiger Schlüssel?

In der web.config muss das neue Konfigurationselement nun noch bekannt gemacht werden, um es anschließend konfigurieren zu können:

<configuration>

	<configSections>
		<section name="responseFilterSettings" type="ResponseFilterConfiguration"/>
	</configSections>

	<responseFilterSettings active="False"></responseFilterSettings>

	...

<configuration>

Der Zugriff auf die Einstellung per Code findet über den ConfigurationManager statt:

Dim rfc As ResponseFilterConfiguration = _
    ConfigurationManager.GetSection("ResponseFilterSettings")
Response.Write(rfc.Active)

Auflistung mehrerer Konfigurationsunterelemente

In meinem Fall war das allerdings erst die halbe Miete, denn ich brauchte unterhalb des Wurzelelements ResponseFilterSettings ja noch eine beliebige Anzahl an Unterelementen. Hierfür stellt das .NET-Framework die Klasse ConfigurationElementCollection bereit, mit der mehrere zusammengehörige Eigenschaften als Liste abgebildet werden können.

Zunächst die Definition der einzelnen Eigenschaften, die in einer eigenen Klasse abgebildet sind, die diesmal von ConfigurationElement erben muss:

'*** Definition der Konfigurationsunterelemente
Public Class ResponseFilterConfigurationElement
    Inherits ConfigurationElement

    <ConfigurationProperty("name", IsRequired:=True, IsKey:=True)> _
    Public ReadOnly Property Name() As String
        Get
            Return CType(MyBase.Item("name"), String)
        End Get
    End Property

    <ConfigurationProperty("pageName", IsRequired:=True)> _
    Public ReadOnly Property PageName() As String
        Get
            Return CType(MyBase.Item("pageName"), String)
        End Get
    End Property

    <ConfigurationProperty("findString", IsRequired:=True)> _
    Public ReadOnly Property FindString() As String
        Get
            Return CType(MyBase.Item("findString"), String)
        End Get
    End Property

    <ConfigurationProperty("newString", IsRequired:=True)> _
    Public ReadOnly Property NewString() As String
        Get
            Return CType(MyBase.Item("newString"), String)
        End Get
    End Property

    <ConfigurationProperty("type", IsRequired:=True)> _
    Public ReadOnly Property Type() As ResponseFilterManipulation
        Get
            Return CType(MyBase.Item("type"), ResponseFilterManipulation)
        End Get
    End Property

End Class

Man beachte, daß zumindest eine eindeutige Eigenschaft definiert sein muss, um später über die Collection auf einen Eintrag zugreifen zu können. Hier ist das, wie in den meisten Fällen, Name. Der Datentyp der Eigenschaft Type verweist auf Werte einer Enumeration namens ResponseFilterManipulation, die außerhalb der Klasse definiert ist.

Public Enum ResponseFilterManipulation
    InsertBefore = 0
    InsertAfter = 1
    Replace = 2
End Enum

Nun zur Definition der Auflistung, wiederum in einer eigenen Klasse, die nun von ConfigurationElementCollection erbt, wobei die beiden Standardmethoden CreateNewElement (Erstellung eines neuen ConfigurationElements) und GetElementKey (Abrufen eines ConfigurationElements) überschrieben werden müssen. Zusätzlich braucht es eine Eigenschaft Item, um ein einzelnes Unterelement abrufen zu können:

'*** Auflistung des Konfigurationsunterelemente
Public Class ResponseFilterConfigurationElementCollection
    Inherits ConfigurationElementCollection

    Protected Overloads Overrides Function CreateNewElement( _
    	) As System.Configuration.ConfigurationElement

        Return New ResponseFilterConfigurationElement
    End Function

    Protected Overrides Function GetElementKey( _
    	ByVal element As System.Configuration.ConfigurationElement) As Object

        Return CType(element, ResponseFilterConfigurationElement).Name
    End Function

    Public Shadows Property Item( _
    	ByVal index As Integer) As ResponseFilterConfigurationElement

        Get
            Return MyBase.BaseGet(index)
        End Get
        Set(ByVal value As ResponseFilterConfigurationElement)
            If (Not (MyBase.BaseGet(index)) Is Nothing) Then
                MyBase.BaseRemoveAt(index)
            End If
            Me.BaseAdd(index, value)
        End Set
    End Property

End Class

Wie man eine solche Auflistung generisch realisieren kann, zeigt Albert Weinert in seinem Artikel Generische ConfigurationElementCollection.

Bleibt noch eine Eigenschaft in der zu Beginn erstellen Hauptklasse ResponseFilterConfiguration anzulegen, um auf die Unterelemente zugreifen zu können. Um sich die Definition einer eigenen GetSection-Methode zu sparen, wird einfach das Attribut IsDefaultCollection der Property gesetzt:

	...
    <ConfigurationProperty("responseFilter", IsRequired:=True, _
        IsDefaultCollection:=True)> _
    Public ReadOnly Property ResponseFilter( _
    	) As ResponseFilterConfigurationElementCollection

    	Get
            Return CType(MyBase.Item("responseFilter"),  _
                ResponseFilterConfigurationElementCollection)
        End Get
    End Property
	...

Der web.config könnte dann zum Beispiel so aussehen:

  <responseFilterSettings active="True">
    <responseFilter>
      <add name="Test1"
              pageName="test.aspx"
              findString="<body"
              newString="<body class="test""
              type="Replace" />
      <add name="Test2"
              pageName="test.aspx"
              findString="</head>"
              newString="<link rel="stylesheet" href="/test.css" type="text/css" />"
              type="InsertBefore" />
    </responseFilter>
  </responseFilterSettings>

(In diesem Beispiel ist darauf zu achten, dass die Werte innerhalt eines Attributs keine spitzen Klammern enthalten dürfen. Sie müssen durch die entsprechenden HTML-Entities ersetzt werden.)

Im übrigen Code können nun die einzelnen Einträge sehr einfach durchlaufen werden:

Dim rfc As ResponseFilterConfiguration = _
	ConfigurationManager.GetSection("responseFilterSettings")

For Each rf As ResponseFilterConfigurationElement In rfc.ResponseFilter
	...
Next

Download: Beispielprojekt (CustomConfigurationSections.zip)

kick it on dotnet-kicks.de AddThis 0 wikio-Stimme(n) Trackback-Url...

1 Kommentar bislang...

  • Test...
    1
    Mein Name : Donnerstag, 28. August 2008 23:37

Dein Kommentar hierzu...


Kommentar-Feed für diesen Beitrag
Gravatare werden unterstützt .:. eMail-Adressen werden nicht veröffentlicht
 

RSS-Feed

Die URL des Standard-Newsfeed von zerbit.de lautet:

http://www.zerbit.de/rssfeed.aspx

Login


 

 

Statistik



kürzlich kommentiert

Artikel 267

  • Datum: 24.08.2008
    Kategorie: ASP.NET
    Zugriffe: 2.875
    Kommentare: 1
    Trackbacks: 0

Letzte Beiträge

Kategorien

Buttons & More

Blog-Roll

Banner Piraten-Partei