Skip to main content

Cloud

How to make web.config changes with a feature and why you should

In many places I see it recommended to change the web.config to turn this on or fix this or add this, these changes work fine in development or single server environments. However if you are going to deploy your fix or feature to a multi-server SharePoint farm and you are planning to make the changes in the web.config manually you are just plain wrong!
Why should I never change the 12,14, 15 hive or the web.config through a text editor you ask? here are a couple of reasons;

  • If your admin adds a new Web Front End to the farm your web.config change does not get applied
  • Admins are really Bad typists and should never be asked to make repeatable changes. As developers we need to take care of our Admins and make sure they have as little work to do as possible. They are already busy fixing the stuff we broke in Test.
  • In my opinion when creating a SharePoint feature it should deploy itself completely when the user hits Activate. There should never be a word document that says here are the manual steps to finish the configuration of this feature.
  • Having all things added through the Feature Receiver provides
    • Repeatability
    • Reliability
    • Documentation
    • And easy ramp up for the guy who has to add those three new feature requests to your awesome solution

Ok so when you set up claims in SharePoint 2010 there are a lot of web.config changes to make. I personally think you could create a feature that would do all this, but in the real word there are some exceptions to every rule and this is probably one. However it does not come without trade offs.
Ok enough with the soap box stuff on with the code. The biggest omission in the MSDN documentation is that they do not tell you, that you need to do this at the web app level. That means your feature should be scoped to WebApplication. This makes perfect sense when you think about it, the change you are making is to the web.config and thus changes the whole web application.
Next you need to use the SPWebConfigModification class to register your modification. These modifications are stored in the farm config database and are implemented whenever a new WFE is added to the farm. It is important to note that when you add a modification you need to remove it in the feature deactivation. I find that most times when I am developing a web.config modification I end up with multiples of the same change registered and need to write some code to clean it up on my dev box.
Below is an example of how to add a Site Map Provider and set it as the default.

 [Guid("d8197d10-5386-4c85-83a6-ca2826778ef9")]
    public class NavigationProviderEventReceiver : SPFeatureReceiver
    {
        private string _navModValue = "<add name='PageNavProvider' type='MySolution.WebFeature.NavigationProviders.PageNavProvider, 
MySolution.WebFeature, Version=1.0.0.0, Culture=neutral, PublicKeyToken=44fdff230d1ebece' NavigationType='Current' EncodeOutput='false' Version='14' />";
        private string _navModPath = "configuration/system.web/siteMap/providers";
        private string _navModName = "add[@name=\"PageNavProvider\"]";
        private string _providerModValue = "PageNavProvider";
        private string _providerModPath = "configuration/system.web/siteMap";
        private string _providerModName = "defaultProvider";
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            Logging.LogApplicationError("Started Navigation feature activation");
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            removeWebConfigSetting(webApp);
            SPWebConfigModification navProviderModification = new SPWebConfigModification(_navModName, _navModPath);
            navProviderModification.Value = _navModValue;
            navProviderModification.Owner = "Some String";
            navProviderModification.Sequence = 0;
            navProviderModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
            webApp.WebConfigModifications.Add(navProviderModification);
            SPWebConfigModification providerProviderModification = new SPWebConfigModification(_providerModName, _providerModPath);
            providerProviderModification.Value = _providerModValue;
            providerProviderModification.Owner = "Some String";
            providerProviderModification.Sequence = 1;
            providerProviderModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
            webApp.WebConfigModifications.Add(providerProviderModification);
            /*Call Update and ApplyWebConfigModifications to save changes*/
            webApp.Update();
            webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            Logging.LogApplicationError("Ended Navigation featue activation");
        }
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
            removeWebConfigSetting(webApp);
        }
        private void removeWebConfigSetting(SPWebApplication webApp)
        {
            SPWebConfigModification foundMod = null;
            if (webApp.WebConfigModifications.Count > 0)
            {
                for (int i = webApp.WebConfigModifications.Count - 1; i >= 0; i--)
                {
                    if (webApp.WebConfigModifications[i].Owner == "Some String")
                    {
                        foundMod = webApp.WebConfigModifications[i];
                        webApp.WebConfigModifications.Remove(foundMod);
                    }
                }
                webApp.Update();
                webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

David Palfery

More from this Author

Follow Us