Wednesday, November 26, 2008

Web Config Modification Feature

Scenario:
You want to automate the modification to Web.config.

Solution:
Intelligent use of Feature receiver can help.

Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace MyClient
{
class WebConfigModifierFeature : SPFeatureReceiver
{
public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }
public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebApplication application = (SPWebApplication)properties.Feature.Parent;

foreach (ModificationEntry entry in this.SectionEntries)
{
application.WebConfigModifications.Add(this.CreateModification(entry.Name, entry.XPath, entry.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureSection ));
}
foreach (ModificationEntry entry2 in this.ChildNodeEntries)
{
application.WebConfigModifications.Add(this.CreateModification(entry2.Name, entry2.XPath, entry2.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode));
}
foreach (ModificationEntry entry3 in this.AttributeEntries)
{
application.WebConfigModifications.Add(this.CreateModification(entry3.Name, entry3.XPath, entry3.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute));
}
application.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
application.Update();
}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWebApplication application = (SPWebApplication)properties.Feature.Parent;

foreach (ModificationEntry entry in this.AttributeEntries)
{
application.WebConfigModifications.Remove(this.CreateModification(entry.Name, entry.XPath, entry.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute ));
}
foreach (ModificationEntry entry2 in this.ChildNodeEntries)
{
application.WebConfigModifications.Remove(this.CreateModification(entry2.Name, entry2.XPath, entry2.Value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode));
}
application.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
application.Update();

}

private struct ModificationEntry
{
public string Name;
public string XPath;
public string Value;

// parameterized contructor
public ModificationEntry( string Name, string XPath, string Value )
{
// intialize structure instances
this.Name = Name;
this.XPath = XPath;
this.Value = Value;
}
}

private ModificationEntry[] AttributeEntries = new ModificationEntry[] {
new ModificationEntry("defaultProvider", "configuration/system.web/membership", "MyMembershipProvider"),
new ModificationEntry("userIsOnlineTimeWindow", "configuration/system.web/membership", "15") };
private ModificationEntry[] ChildNodeEntries = new ModificationEntry[] {
new ModificationEntry("add[@name='MyConnectionString']", "configuration/connectionStrings", "<add name=\"MyConnectionString\" connectionString=\"Data Source=myserver;Initial Catalog=mydb;User Id=USER1;Password= pass@word!;\" providerName=\"System.Data.SqlClient\" />"),
new ModificationEntry("add[@name='MyMembershipProvider']", "configuration/system.web/membership/providers", "<add name=\"MyMembershipProvider\" type=\"GlobalConfigFeature.MyMembershipProvider, GlobalConfigFeature, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c64981f6ea780b0\" applicationName=\"/\" passwordFormat=\"Clear\" description=\"Authenticates users against CRM\" connectionstring=\"CRM4M\"/>"),
new ModificationEntry("add[@name='MyHttpHandler']", "configuration/system.web/httpModules", "<add name=\"MyHttpHandler\" type=\"GlobalConfigFeature.MyHttpHandler,GlobalConfigFeature, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c64981f6ea780b0\" />"),
new ModificationEntry("add[@key='MyMembershipProvider']", "configuration/SharePoint/PeoplePickerWildcards", "<add key=\"MyMembershipProvider\" value=\"%\" />"),
new ModificationEntry("add[@key='UseCustomProfileDashboard']", "configuration/appSettings", "<add key=\"UseCustomProfileDashboard\" value=\"false\" />") };
private ModificationEntry[] SectionEntries = new ModificationEntry[] {
new ModificationEntry("appSettings", "configuration", "appSettings"),
new ModificationEntry("connectionStrings", "configuration", "connectionStrings"),
new ModificationEntry("membership", "configuration/system.web", "membership"),
new ModificationEntry("providers", "configuration/system.web/membership", "providers") };

public SPWebConfigModification CreateModification(string Name, string XPath, string Value, SPWebConfigModification.SPWebConfigModificationType Type)
{
SPWebConfigModification modification = new SPWebConfigModification(Name, XPath);
modification.Owner ="MyClient";
modification.Sequence= 0;
modification.Type=Type;
modification.Value= Value;
return modification;
}
}
}
Article:
Reza , Ted Pattison , Mark

Follow up:
While discussing the manageability of the Web.Config changes ( specially AppSettings ) , as they were growing fast. I wrote a modified version of the same feature here

0 comments: