Datenzugriff in SharePoint: web.config

3. August 2012

Dies ist der fünfte Teil einer Serie, die sich mit der Frage beschäftigt auf welche Arten Konfigurationen in Applikationen unter SharePoint gespeichert werden können. Es wird zuerst immer kurz die Methode vorgestellt, gefolgt von einem kurzen Beispiel und den Vor- und Nachteilen.

Eine vollständige Übersicht über bisherige und noch folgende Artikel ist hier zu finden.

In heutigen Teil widmen wir uns dem Speichern von Konfiguration über eine web.config Datei. Die Verwendung einer web.config in SharePoint ist komplizierter als man vermuten sollte. Das Auslesen von Konfigurationseinträgen ist hierbei noch kein Problem und funktioniert wie gewohnt bei nicht SharePoint Anwendungen. Die Schwierigkeiten tauchen erst auf wenn versucht wird Änderungen an der Konfiguration in der Farm zu verteilen. Features verfügen nicht über eine eigene Konfigurationsdatei, sondern verwenden zusammen mit allen Applikationen und Services die globale web.config der IIS-Web-Site.

Das Problem besteht also darin, die benötigten Einträge in die bestehende web.config zu integrieren ohne diese dabei kaputt zu machen. Glücklicherweise bietet SharePoint genau hierfür einen einfachen Mechanismus: die Klasse SPWebConfigModification. Mit dieser lassen sich Einträge problemlos hinzufügen und auch wieder entfernen.

Die Klasse SPWebConfigModification definiert einen Konfigurationseintrag über folgende Eigenschaften:

  • Path – XPath Ausdruck, welcher die Position innerhalb der web.config definiert
  • Type – Hier gibt es drei verschiedene Typen:
    • EnsureAttribute – Die Modifikation ändert den Wert eines Attributes.
    • EnsureChildNode – Die Modifikation fügt einen Knoten hinzu oder entfernt ihn
    • EnsureSection – Modifikation ändert eine komplette Sektion
  • Name – Identifiziert den Knoten zusammen mit der Path Eigenschaft eindeutig. Hier ist also auch ein XPath Ausdruck notwendig.
  • Sequence – Ein Index für den Fall wenn mehrere Modifikationen mit dem gleichen Typ und Namen hinzugefügt werden sollen. Sollte Standardmäßig immer “0” sein.
  • Owner – Identifiziert den “Besitzer” der Modifikation. Kann verwendet werden um alle Modifikationen welche zu einer Applikation gehören zu identifizieren z.B. wenn bei der Deinstallation eines Features alle dazugehörigen Konfigurationseinträge wieder entfernt werden. Es sollte daher unbedingt eindeutig sein.
  • Value – XML Knoten oder Attribut, welches hinzugefügt werden soll.

Beispiel

Der geeignete Zeitpunkt um benötigte Einträge in der web.config anzulegen, ist beim Aktivieren des Features. Hierfür benötigen das Feature einen so genannten Event Receiver. Diesen erstellen wir in Visual Studio mit einem Rechtsklick auf das entsprechende Feature:

501

Visual Studio legt innerhalb des Features eine neue Klasse mit vier auskommentierten Methoden an, welche virtuelle Methoden der Basisklasse überschreiben. Im Folgenden ist es dann notwendig, diese virtuellen Methoden weiter auszuformulieren:

public class BeispielFeatureEventReceiver : SPFeatureReceiver

{

// Uncomment the method below to handle the event raised after a feature has been activated.

 

//public override void FeatureActivated(SPFeatureReceiverProperties properties)

//{

//}

 

 

// Uncomment the method below to handle the event raised before a feature is deactivated.

 

//public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

//{

//}

 

 

// Uncomment the method below to handle the event raised after a feature has been installed.

 

//public override void FeatureInstalled(SPFeatureReceiverProperties properties)

//{

//}

 

 

// Uncomment the method below to handle the event raised before a feature is uninstalled.

 

//public override void FeatureUninstalling(SPFeatureReceiverProperties properties)

//{

//}

 

// Uncomment the method below to handle the event raised when a feature is upgrading.

 

//public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)

//{

//}

}

Zuerst passen wir die Methode „FeatureActivated“ an, und fügen folgenden Code hinzu:

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

// Site öffnen in welche unser Feature installiert wurde

using (var site = ((SPSite)properties.Feature.Parent))

{

site.WebApplication.WebConfigModifications.Clear();

site.WebApplication.Update();

site.WebApplication.WebService.ApplyWebConfigModifications();

 

// Knoten "connectionStrings" erstellen, falls noch nicht vorhanden

var connectionNode = new SPWebConfigModification

{

Path = "configuration",

Name = "connectionStrings",

Sequence = 0,

Owner = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,

Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection,

Value = "<connectionStrings />"

};

 

// Connectionstring erstellen

var rootNode = new SPWebConfigModification

{

Path = "configuration/connectionStrings",

Name = "add[@name="" + ConfigName + ""]",

Sequence = 0,

Owner = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name,

Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,

Value = "<add name="" + ConfigName + "" "

+

"connectionString="metadata=res://*/ModelDemo.csdl|res://*/ModelDemo.ssdl|res://*/ModelDemo.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.;Initial Catalog=Uptime;Integrated Security=True;MultipleActiveResultSets=True&quot;" "

+ "providerName="System.Data.EntityClient" />"

 

};

 

// Neue Knoten hinzufügen

site.WebApplication.WebConfigModifications.Add(connectionNode);

site.WebApplication.WebConfigModifications.Add(rootNode);

 

// Änderungen speichern und Anpassungen verteilen

site.WebApplication.Update();

site.WebApplication.WebService.ApplyWebConfigModifications();

}

}

Wenn das Feature deaktiviert wird, müssen die Einträge natürlich auch wieder entfernt werden. Dies geschieht in der Methode FeatureDeactivating, welche wir als nächstes auskommentieren:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

{

// Site öffnen in welche unser Feature installiert wird

using (var site = ((SPSite)properties.Feature.Parent))

{

var webApp = site.WebApplication;

// "Unsere" Modifikationen ermitteln

var mods = (from m in webApp.WebConfigModifications

where m.Owner == System.Reflection.Assembly.GetExecutingAssembly().GetName().Name

select m).ToList();

 

// Modifikationen löschen

mods.ForEach(m => webApp.WebConfigModifications.Remove(m));

 

// Änderungen speichern und Anpassungen verteilen

webApp.Update();

webApp.WebService.ApplyWebConfigModifications();

}

}

Fazit

Zum Abschluss wieder die Vor- und Nachteile der hier vorgestellten Methode:

Vorteile:

  • Implementierung

    Datenzugriff funktioniert wie gewohnt von nicht SharePoint Anwendungen. Zum Verteilen der Konfiguration sind ein paar zusätzliche Zeilen Code erforderlich, aber alles in allem einfach umzusetzen.

  • Wartbarkeit

    Die Klasse SPWebConfigModification class kümmert sich um die Verteilung innerhalb der Farm.

Nachteile:

  • Administration

    Es gibt keine mitgelieferte Oberfläche zum Verwalten der Werte.

  • Wartbarkeit

    Änderungen an der web.config können von Service Packs oder Updates überschrieben werden. Dies kann zu Problemen führen.

    Darüber werden Konfigurationseinträge beim Deployment nicht von SharePoint validiert. Es kann also sehr schnell passieren, dass die web.config nach einem Deployment ungültige Einträge enthält und somit der komplette SharePoint nicht mehr zu erreichen ist!

  • Scope

    Einstellungen gelten global. Es ist also sehr schwierig Einstellungen pro Benutzer zu speichern.