SharePoint, Features and web.config modifications using SPWebConfigModification

SharePoint has a great way for deploying content and functionality using Windows SharePoint Services Solution Packages (WSP's). While developing a powerful new feature for SharePoint Publishing sites I had to deploy a HttpModule "the SharePoint" way. Building a HttpModule , a corresponding feature and the resulting WSP package is easy with our Macaw Solutions Factory. The actual logic in the Http Module and the feature is the difficult part. One of the things I had to do was to create a feature that registers a HTTPModule on feature activation, and removes it from the web.config on the feature deactivation. You can do this using the SPWebConfigModification class.

A good article on this topic is http://www.crsw.com/mark/Lists/Posts/Post.aspx?ID=32. It contains links to other posts as well.

The Microsoft documentation can be found at SPWebConfigModification Class (Microsoft.SharePoint.Administration), I wished I scrolled down before, because a lot of valuable information can be found in the Community Content of this page (keep scrolling!).

Anyway, it took quite some time to get my HttpModule to register/unregister correctly on activation/deactivation of my web application level feature. I post the code below so you have a head-start if you have to do something similar yourself.

 

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

// namespace must be in the form <Company>.<Product>.<FunctionalArea>.SharePoint.Features.<FeatureName>.FeatureReceiver namespace Macaw.WcmRia.Moss2007.DualLayout.SharePoint.Features.DualLayoutSupport.FeatureReceiver { /// <summary> /// Add HttpModule registration to web.config of the web application /// </summary> class DualLayoutSupportFeatureReceiver : SPFeatureReceiver { private const string WebConfigModificationOwner = "Macaw.WcmRia.Moss2007.DualLayout"; private static readonly SPWebConfigModification[] Modifications = { // For not so obvious reasons web.config modifications inside collections // are added based on the value of the key attribute in alphabetic order. // Because we need to add the DualLayout module after the // PublishingHttpModule, we prefix the name with 'Q-'. new SPWebConfigModification() { // The owner of the web.config modification, useful for removing a // group of modifications Owner = WebConfigModificationOwner, // Make sure that the name is a unique XPath selector for the element // we are adding. This name is used for removing the element Name = "add[@name='Q-Macaw.WcmRia.Moss2007.DualLayout']", // We are going to add a new XML node to web.config Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, // The XPath to the location of the parent node in web.config Path = "configuration/system.web/httpModules", // Sequence is important if there are multiple equal nodes that // can't be identified with an XPath expression Sequence = 0, // The XML to insert as child node, make sure that used names match the Name selector Value = "<add name='Q-Macaw.WcmRia.Moss2007.DualLayout' type='Macaw.WcmRia.Moss2007.DualLayout.Business.Components.HttpModule, Macaw.WcmRia.Moss2007.DualLayout.Business.Components, Version=1.0.0.0, Culture=neutral, PublicKeyToken=077f92bbf864a536' />" } };

    <span style="color: blue">public override void </span>FeatureInstalled(<span style="color: #2b91af">SPFeatureReceiverProperties </span>properties)
    {
    }

    <span style="color: blue">public override void </span>FeatureUninstalling(<span style="color: #2b91af">SPFeatureReceiverProperties </span>properties)
    {
    }

    <span style="color: blue">public override void </span>FeatureActivated(<span style="color: #2b91af">SPFeatureReceiverProperties </span>properties)
    {
        <span style="color: #2b91af">SPWebApplication </span>webApp = properties.Feature.Parent <span style="color: blue">as </span><span style="color: #2b91af">SPWebApplication</span>;
        <span style="color: blue">if </span>(webApp != <span style="color: blue">null</span>)
        {
            AddWebConfigModifications(webApp, Modifications);
        }
    }

    <span style="color: blue">public override void </span>FeatureDeactivating(<span style="color: #2b91af">SPFeatureReceiverProperties </span>properties)
    {
        <span style="color: #2b91af">SPWebApplication </span>webApp = properties.Feature.Parent <span style="color: blue">as </span><span style="color: #2b91af">SPWebApplication</span>;
        <span style="color: blue">if </span>(webApp != <span style="color: blue">null</span>)
        {
            RemoveWebConfigModificationsByOwner(webApp, WebConfigModificationOwner);
        }
    }

    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Add a collection of web modifications to the web application
    </span><span style="color: gray">/// &lt;/summary&gt;
    /// &lt;param name=&quot;webApp&quot;&gt;</span><span style="color: green">The web application to add the modifications to</span><span style="color: gray">&lt;/param&gt;
    /// &lt;param name=&quot;modifications&quot;&gt;</span><span style="color: green">The collection of modifications</span><span style="color: gray">&lt;/param&gt;
    </span><span style="color: blue">private void </span>AddWebConfigModifications(<span style="color: #2b91af">SPWebApplication </span>webApp, <span style="color: #2b91af">IEnumerable</span>&lt;<span style="color: #2b91af">SPWebConfigModification</span>&gt; modifications)
    {
        <span style="color: blue">foreach </span>(<span style="color: #2b91af">SPWebConfigModification </span>modification <span style="color: blue">in </span>modifications)
        {
            webApp.WebConfigModifications.Add(modification);
        }

        <span style="color: green">// Commit modification additions to the specified web application
        </span>webApp.Update();
        <span style="color: green">// Push modifications through the farm
        </span>webApp.WebService.ApplyWebConfigModifications();
    }

    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Remove modifications from the web application
    </span><span style="color: gray">/// &lt;/summary&gt;
    /// &lt;param name=&quot;webApp&quot;&gt;</span><span style="color: green">The web application to remove the modifications from</span><span style="color: gray">&lt;/param&gt;
    /// &lt;param name=&quot;owner&quot;Remove all modifications that belong to the owner&gt;&lt;/param&gt;
    </span><span style="color: blue">private void </span>RemoveWebConfigModificationsByOwner(<span style="color: #2b91af">SPWebApplication </span>webApp, <span style="color: blue">string </span>owner)
    {
        <span style="color: #2b91af">Collection</span>&lt;<span style="color: #2b91af">SPWebConfigModification</span>&gt; modificationCollection = webApp.WebConfigModifications;
        <span style="color: #2b91af">Collection</span>&lt;<span style="color: #2b91af">SPWebConfigModification</span>&gt; removeCollection = <span style="color: blue">new </span><span style="color: #2b91af">Collection</span>&lt;<span style="color: #2b91af">SPWebConfigModification</span>&gt;();

        <span style="color: blue">int </span>count = modificationCollection.Count;
        <span style="color: blue">for </span>(<span style="color: blue">int </span>i = 0; i &lt; count; i++)
        {
            <span style="color: #2b91af">SPWebConfigModification </span>modification = modificationCollection[i];
            <span style="color: blue">if </span>(modification.Owner == owner)
            {
                <span style="color: green">// collect modifications to delete
                </span>removeCollection.Add(modification);
            }
        }

        <span style="color: green">// now delete the modifications from the web application
        </span><span style="color: blue">if </span>(removeCollection.Count &gt; 0)
        {
            <span style="color: blue">foreach </span>(<span style="color: #2b91af">SPWebConfigModification </span>modificationItem <span style="color: blue">in </span>removeCollection)
            {
                webApp.WebConfigModifications.Remove(modificationItem);
            }

            <span style="color: green">// Commit modification removals to the specified web application
            </span>webApp.Update();
            <span style="color: green">// Push modifications through the farm
            </span>webApp.WebService.ApplyWebConfigModifications();
        }
    }
}

}

39 Comments

  • Nice post Serge, I stored it in my del.icio.us collection.

  • Trust me , this will only work on your own VM.. never on Production..

  • Sandeep, can you give more information on why this will not work in a production environment?

    I am currently implementing this and it would help if you said why it won't work in prod so that I can change whatever needs to be changed to ensure it does work.

  • Exactly what I needed. Thanks for the article.

  • Hi Serge,
    there are some issues with calling: webApp.WebService.ApplyWebConfigModifications();
    I don't know if you've tested this in a farm environment, but I never got it to work..

    This is the alternative I'm using:
    webApp.Farm.Services.GetValue().ApplyWebConfigModifications();

    See ya!
    Sander

  • I've successfully applied the SPWebConfigModifcation functionality in several projects, both for rolling out new or updated versions in local VM, and when rolling out to test, staging and production servers - within a farm setup. The infra setups are various: pure intranet with multiple WFEs, a web app extended in extra zone to internet, web app extended for intra- and extranet. Overall, good and repetive consequent results, both upon adding as removal/retraction.
    I did apply a variant of the call to apply the modifications:
    SPFarm.Local.Services.GetValue().ApplyWebConfigModifications();

  • Serge,

    Do you know if the order trick still works in SharePoint 2010? I tried yours (and several others that I know worked in SP2007), but they all failed in SharePoint 2010...

  • Hello,

    I am new to SharePoint development and I need help me make this work. I am trying to apply the above method to add authorizedType node in web.config. I am not getting error message but when I activate the feature, no node is getting added in web.config. I checked the port and I also tried webApp.Farm.Services.GetValue().ApplyWebConfigModifications() but nothing seems to work. I wonder what I am missing. Can anybody spot what is wrong with my code:

    new SPWebConfigModification()
    {
    Owner = WebConfigModificationOwner,
    Name = "authorizedType[@Namespace='org.dept.customcode']",
    Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,
    Path = "configuration/System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes",
    Sequence = 0,
    Value = ""
    }

    Thanks in advance!

    - Jeck

  • Any hint as to how to do the same for the STS web config in sharePoint 2010 with Forms authentication?
    Thanks.

  • bPUAPT I loved your blog article.Thanks Again. Awesome.

  • Hey, thanks for the post.Thanks Again. Cool.

  • Very neat article post.Thanks Again. Really Great.

  • Sorry for the off-topic, could you tell where I can get such a nice pattern for my blog ?!...

  • Thanks a lot for the blog.Much thanks again. Keep writing.

  • Hi i am kavin, its my first occasion to commenting anywhere, when i read this paragraph i thought
    i could also make comment due to this sensible article.

  • Hi,this article is great,I found it on google and I love it very much.

  • pJYU6x Looking forward to reading more. Great blog. Really Great.

  • Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point.
    You clearly know what youre talking about, why waste your intelligence on just posting videos to your weblog
    when you could be giving us something enlightening
    to read?

  • Do you mind if I quote a few of your articles as long as I
    provide credit and sources back to your weblog? My
    blog is in the exact same niche as yours and my visitors
    would definitely benefit from a lot of the information you provide here.
    Please let me know if this alright with you.
    Many thanks!

  • What i don't realize is in truth how you're no longer actually a
    lot more neatly-favored than you may be right now. You are very intelligent.
    You realize thus significantly in relation to this subject,
    produced me in my view believe it from so many varied angles.

    Its like men and women don't seem to be involved except it is something to do with Lady gaga! Your own stuffs nice. At all times take care of it up!

  • It's hard to come by educated people about this topic, however, you seem like you know what you're talking about!
    Thanks

  • I visited various web sites except the audio feature for audio songs existing
    at this site is truly fabulous.

  • For most up-to-date news you have to pay a quick
    visit world-wide-web and on the web I found this web page
    as a best site for most recent updates.

  • Though it is often used as a topical ointment and it can help reverse chronic damage associated with some auto-immune disorders.
    Dec 15, 2010, 10:38pm EST Well, it looks tolerable so far.
    But when you start interacting with the person observing hijab,
    you will start to feel nauseaous, lie down, breath slow and
    have you eyes closed.

  • Way cool! Some very valid points! I appreciate you penning this article and the rest of the website is also very good.

  • I'm truly enjoying the design and layout of your site. It's a very
    easy on the eyes which makes it much more pleasant for me to come here and visit more often.
    Did you hire out a designer to create your theme? Fantastic work!

  • Pretty nice post. I just stumbled upon your weblog and wanted to say that I have really enjoyed browsing your
    blog posts. In any case I will be subscribing to your feed and I hope you write again very soon!

  • I drop a comment whenever I like a post on a website or I have something to valuable to contribute to the discussion.
    It is caused by the passion displayed in the article I read.
    And after this article SharePoint, Features and
    web.config modifications using SPWebConfigModification
    - Serge van den Oever [Macaw]. I was actually moved enough to
    post a comment ;) I do have a couple of questions for
    you if it's okay. Is it simply me or does it look as if like some of the comments come across as if they are written by brain dead visitors? :-P And, if you are posting on additional social sites, I would like to follow you. Could you make a list every one of all your shared pages like your linkedin profile, Facebook page or twitter feed?

  • My brother recommended I might like this website. He
    was totally right. This post truly made my day. You can not imagine
    simply how much time I had spent for this information!
    Thanks!

  • You ought to be a part of a contest for one of
    the most useful sites on the internet. I most certainly
    will recommend this site!

  • Hi this is kind of of off topic but I was wondering
    if blogs use WYSIWYG editors or if you have to manually code with
    HTML. I'm starting a blog soon but have no coding skills so I wanted to get guidance from someone with experience. Any help would be enormously appreciated!

  • Excellent web site you have here.. It's difficult to find high quality writing like yours nowadays. I honestly appreciate individuals like you! Take care!!

  • What i do not understood is if truth be told how you are now not really
    a lot more well-favored than you might be now. You're very intelligent. You know therefore considerably relating to this subject, produced me in my opinion consider it from numerous varied angles. Its like men and women don't
    seem to be involved except it is something to do with Lady gaga!

    Your personal stuffs excellent. At all times handle it up!

  • Hello there, just became aware of your blog through Google, and found that it's really informative. I'm gonna watch out for brussels.
    I will appreciate if you continue this in future. Numerous people will be
    benefited from your writing. Cheers!

  • I'm really impressed along with your writing skills and also with the format for your weblog. Is this a paid theme or did you modify it yourself? Anyway keep up the nice quality writing, it is uncommon to look a great weblog like this one nowadays..

  • I have read so many posts concerning the blogger lovers but this article is truly a fastidious piece of writing, keep it up.

  • It's remarkable to pay a quick visit this web page and reading the views of all mates about this article, while I am also eager of getting know-how.

  • If you would like to improve your experience simply keep visiting this website
    and be updated with the most up-to-date news posted here.

  • I like what you guys tend to be up too. This type of clever
    work and reporting! Keep up the great works guys I've added you guys to my own blogroll.

Comments have been disabled for this content.