Copy web.config settings using a SharePoint Feature
Explanation:
For most of the projects, it is usually required to add few web.config entries.
Adding them in the WFE servers manually is prone to mistakes.
Deploying them as a feature ensures that its not only clean but also eases the job of administrators if a new WFE server is added in the future.
Lets take the scenario where we had to update web.config with entries for Telerik Controls
Code:
//Feature.xml
<?xml version="1.0" encoding="utf-8"?> <Feature Id="[ID]" Title="Telerik Controls" Description="This feature adds the required Telerik Web.Config entries and assosiated dlls" Version="1.0.0.0" Scope="WebApplication" Hidden="false" ImageUrl="TelerikControls\img.jpg" ReceiverAssembly="TelerikControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d6ff03c5a94c295d" ReceiverClass="TelerikControls.TelerikControlsFeatureReceiver" xmlns="http://schemas.microsoft.com/sharepoint/"> <ElementManifests> <ElementFile Location="Web.Config" /> </ElementManifests> </Feature>
//Web.Config
<configuration> <!-- SafeControls for Telerik --> <SharePoint> <SafeControls> <SafeControl Assembly="Telerik.Web.Design, Version=2009.2.701.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.Design" TypeName="*" Safe="True" /> <SafeControl Assembly="Telerik.Web.UI, Version=2009.2.701.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" Namespace="Telerik.Web.UI" TypeName="*" Safe="True" /> </SafeControls> </SharePoint> <system.web> <httpHandlers> <add verb="*" validate="false" path="Telerik.Web.UI.DialogHandler.axd" type="Telerik.Web.UI.DialogHandler, Telerik.Web.UI, Version=2009.2.701.35, Culture=neutral, PublicKeyToken=121fae78165ba3d4" /> </httpHandlers> </system.web> </configuration>
//FeatureReceiver
using System.Xml; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; namespace TelerikControls { public class TelerikControlsFeatureReceiver : SPFeatureReceiver { public override void FeatureActivated(SPFeatureReceiverProperties properties) { string xPath; SPWebApplication webApp; WebConfigModifications webConfigMods; XmlDataDocument xmlDoc; webApp = (SPWebApplication)properties.Feature.Parent; webConfigMods = new WebConfigModifications(); //load the web.config settings from the feature root xmlDoc = new XmlDataDocument(); xmlDoc.Load(string.Format("{0}\\{1}", properties.Feature.Definition.RootDirectory, "web.config")); //configuration/SharePoint/SafeControls xPath = "configuration/SharePoint/SafeControls"; AddWebConfigNodes(xPath, ref xmlDoc, ref webConfigMods, ref webApp); //configuration/system.web/httpHandlers xPath = "configuration/system.web/httpHandlers"; AddWebConfigNodes(xPath, ref xmlDoc, ref webConfigMods, ref webApp); //set full trust SPWebConfigModification modification = new SPWebConfigModification("level", "configuration/system.web/trust"); modification.Owner = "WebConfigTrust"; modification.Sequence = 0; modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute; modification.Value = "Full"; webApp.WebConfigModifications.Add(modification); webApp.Farm.Servers.GetValue<SPWebService>().ApplyWebConfigModifications(); webApp.Update(); } private void AddWebConfigNodes(string xPath, ref XmlDataDocument xmlDoc, ref WebConfigModifications webConfigMods, ref SPWebApplication webApp) { foreach (XmlNode node in xmlDoc.SelectSingleNode(xPath)) if (node.NodeType != XmlNodeType.Comment) webConfigMods.AddWebConfigNode(webApp, xPath, node, node.Attributes); } public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent; WebConfigModifications webConfigMods = new WebConfigModifications(); webConfigMods.RemoveWebConfigNodes(webApp); webApp.Farm.Servers.GetValue<SPWebService>().ApplyWebConfigModifications(); webApp.Update(); } public override void FeatureInstalled(SPFeatureReceiverProperties properties) { /* no op */ } public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { /* no op */ } } }
//Helpers
using System.Xml; using System.Text; using Microsoft.SharePoint.Administration; using System.Collections.ObjectModel; namespace TelerikControls { public class WebConfigModifications { public string Owner { get { return this.GetType().FullName; } } private string GetWebConfigModName(string nodeName, XmlAttributeCollection attributes) { StringBuilder webConfigModName = new StringBuilder(nodeName); foreach (XmlAttribute attribute in attributes) { webConfigModName.Append(string.Format("[@{0}=\"{1}\"]", attribute.Name, attribute.Value)); } return webConfigModName.ToString(); //return string.Format("add[@key=\"{0}\"]", key); } private string GetWebConfigModValue(string nodeName, XmlAttributeCollection attributes) { XmlDataDocument xDoc = new XmlDataDocument(); XmlAttribute newAttribute; XmlNode modValueNode = xDoc.AppendChild(xDoc.CreateElement(nodeName)); foreach (XmlAttribute attribute in attributes) { newAttribute = xDoc.CreateAttribute(attribute.Name); newAttribute.Value = attribute.Value; modValueNode.Attributes.Append(newAttribute); } return string.Format("{0}\n", modValueNode.OuterXml); } private string GetFirstNodeName(ref XmlDataDocument xDoc) { string xPath = xDoc.FirstChild.Name; //we don't want to process the xml declaration node if (xPath == "xml") { if (xDoc.FirstChild.NextSibling != null) { xPath = xDoc.FirstChild.NextSibling.Name; } else { xPath = string.Empty; } } return xPath; } /// <summary> /// Adds the key/value pair as an appSettings entry in the web application's /// SPWebConfigModification collection /// </summary> /// <param name="webApp">Current web application context</param> /// <param name="key">appSettings node key</param> /// <param name="value">appSettings node value</param> public void AddWebConfigNode(SPWebApplication webApp, string webConfigModxPath, XmlNode node, XmlAttributeCollection attributes) { SPWebConfigModification webConfigMod; string webConfigModName; webConfigModName = GetWebConfigModName(node.Name, attributes); webConfigMod = new SPWebConfigModification(webConfigModName, webConfigModxPath); webConfigMod.Owner = this.Owner; webConfigMod.Sequence = 0; webConfigMod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode; webConfigMod.Value = node.OuterXml; webApp.WebConfigModifications.Add(webConfigMod); } /// <summary> /// Removes the key from the appSettings the web application's /// SPWebConfigModification collection /// </summary> /// <param name="webApp">Current web application context</param> /// <param name="key">appSettings node key</param> public void RemoveWebConfigNodes(SPWebApplication webApp) { Collection<SPWebConfigModification> collection; SPWebConfigModification[] tempCollection; string webConfigModName; int iStartCount; SPWebConfigModification webConfigMod; collection = webApp.WebConfigModifications; tempCollection = new SPWebConfigModification[collection.Count]; collection.CopyTo(tempCollection, 0); iStartCount = collection.Count; // Remove any modifications that were originally created by the owner. for (int c = iStartCount - 1; c >= 0; c--) { webConfigMod = collection[c]; if (webConfigMod.Owner == this.Owner) collection.Remove(webConfigMod); } } } }
What Telerik has to do with this ?
ReplyDelete@ Sandeep K Nahta.. It is quite obvious that I just gave an example of a real time scenario. In this case, it happened to be the config entries that need to be added for Telerik controls
ReplyDelete