SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

So you think you can change your Web Config?

News


  • Feb 9 2009   Now with added Sigma
    I've been tardy updating this blog, as I've become part of SevenSigma Business Solutions, a boutique sharepoint advisory and consultancy run and staffed by people I've worked with, known and respected for many years. It's a breath of fresh air to be with like-minded souls who's central remit is NOT to repeat those same buisness and IT projects blunders we all blog about!

    Mar 17 2008   Commuting this AM I independently ran into 3 ex-colleagues from the same small firm. Now I know Perth isn't big, but that is just too weird & 'paranoidal'. So Chris, Dan and Sean - stop dabbling in Occult over IpEspFi V6 - it's freaking me out!

    Feb 20 2008   Aussie day has been and gone and things have been hectic, but I'm now on a course with the irrepressible Clayton James - with many ideas to blog about!

    Jan 21 2008   Back again, with the promised info on moving those web pages in code.

    Jan 16 2008   I'm away for a few days for a Geraldton funeral (sniff), but back in Perth I'll have something to say about moving pages between webs...

    Jan 14 2008   Happy New Year and a Happy New Blog to all - especially MOSS masters Mr P.CleverWorkarounds and Sezai "Yoda"!

or 'Making a Feature of SPWebConfigModifications'

Part 1 - A Winner from SharePoint

I know, we've all done it. Jumped into the web config and messed it about for our own evil ends (and we might even have taken a backup first).

Well in the brave new SharePoint world, beyond your 'playpen' dev box, that just ain't allowed!

So what do you do when there's a must have app setting you can't/won't deploy via a WSP solution (please oh please leave your solution to do all the standard things like safe control entries) and you want them to follow wherever your Feature goes?

NB: MrCleverWorkArounds, the Guru of Governance, tells me there may be some issues with what I'm doing here if the feature isn't at WebApplication or Farm scope (as you would expect messing about with web apps configs), so expect a review of this once he's run his strict ruler over it!

Well, there is a little known (it has been news to a couple of SharePoint Gods I occasionally ask silly questions of) part of the object model to help us.

On each web app (Microsoft.SharePoint.Administration.SPWebApplication) there is a property called WebConfigModifications which is a collection of these guys: Microsoft.SharePoint.Administration.SPWebConfigModification

They are just the ticket! You can add and remove modifications to the collection, they don't break if the entry is already in there or isn't there to be removed. If you want to you can even mess with things like debug settings.

spWebApp.WebConfigModifications.Add(configMod1);

spWebApp.WebConfigModifications.Remove(configMod2);

spWebApp.WebConfigModifications.Remove(configMod2);

spWebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();  // propagate across farm
spWebApp.Update();

So the logical next step is to add them in your FeatureActivated and remove them in your FeatureDeactivating SPFeatureReceiver events.

Ah, this is where we hit some small snags:

1. We don't really want to hardcode the updates
2. We only want to remove those from our feature, so probably need to remember a SPWebConfigModification.Owner property.
3. The SPWebConfigModification Class seems to rely on us setting xPath strings to do its things.
4. There are some other properties we need to set.

But fear not. I wrote some simple XML serialisable classes for the base entries, app settings, sections and connection strings. That way I can build those classes up, and serialise them to a file in code, to give you a nice guaranteed valid starting structure. Here's an example of the XML that results:

<?

xml version="1.0"?>
<
SPwebconfigMods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     <
Owner>mrwaUtils.UtilsFeatureReceiver</Owner>
     <
Entries>
          <
Entry xsi:type="AppSettingsAddEntry">
               <
Name>mrwaUtils.Logging.Log+DestinationTypes.EventLog</Name>
               <
Value>MACHINE01</Value>
               <
Xpath>//configuration/appSettings</Xpath>
               <
ModificationType>EnsureChildNode</ModificationType>
               <
Sequence>10</Sequence>
               <
SetValueFromEnvVar>true</SetValueFromEnvVar>
          </
Entry>
     </Entries>
</
SPwebconfigMods>

...and this can be deployed with your Feature as a file, so your receiver can find it.

I'll go through this XML from my class, as it also nicely details the properties for the SPWebConfigModification class that does the real work:

The AppSettingsAddEntry class contains all the entries we need for an app setting (specialised from my base Entry class) with properties, such as the xpath, defaulting to the correct value so we don't have to worry about setting them or making a mistake - you can set them to something else if you want to though.

My containing class SPwebconfigMods class has the owner (this could be the feature GUID, but I've just gone with the Feature's Receiver type). This is the one small difference between my object graph and the SPWebConfigModification class - I only put the owner on the container class, SPwebconfigMods, and all mods will use that. Just remember it actually lives on the SPWebConfigModification class.

Name and Value are my base properties for the simplest NVP Entry style, and match those on the SharePoint class. Where my subclasses have more properties (such as connection strings), at serialise time they are concatenated onto the name/value properties using an override and serialised out/in.

The ModificationType can have 3 values: EnsureChildNode, EnsureAttribute and EnsureSection.

The Sequence determines the order they are applied in, so if you have a section you have to add, ensure it's number is lower than the values it contains. In the above example this class defaults to 10 as it is in the second level of the xpath - if there were sub items I'd set those classes to 20 be default, and the parent to 0 etc.

The SetValueFromEnvVar is one of my own additions, so don't worry about it too much. Suffice to say, this allows me to pick up environment variables, from a batch file of via policies, at actiuvation time. This is an optional way I make releasing the same image accross different enviroments more manageable - the downside is you don't have a record of what was set in the SPwebconfig.xml file. Therefore the results in your web config could be different next time the feature is activated. This is different to actually placing a %SomeEnvVar% ref in the web config, which could then vary every time accessed. My preferece is not to do this, but to read from env vars at file creation time, so they are recorded and fixed after the first install. You pays yer money...

NB2: I've seen a project, I think on codeplex, that allows the management of these updates through a web interface - a very nice idea if you are comfortable with the parameters (more of those later). Obviously add/removing features that change these will mean you loose those interactive changes, so if I get a change I'll see if that project has an export/view facility so we can get them back into our feature (perhaps with some XSLT).  I think Ted Pattison is the originator of that project. The Kid also has a page/solution you can download to edit these interactively from within sharepoint.

So how does this end up looking in my feature receiver? Every time I need web config changes in a feature I inherit from my base class like this:

public
class UtilsFeatureReceiver : ConfigSPFeatureReceiver
{
   
    public override SPwebconfigMods SPwebconfigModsFeatureActivatedFileEntries(Guid featureGuid)
    {
        // Optional method used to create SPwebConfigMods if xml file not found
        // Try to get the required setting from environment variables:
        string machineNameKey = "mrwaUtils.Logging.Log+DestinationTypes.EventLog";
        string machineName = Environment.GetEnvironmentVariable(machineNameKey);
        if (machineName == null || machineName.Trim().Length == 0)
        machineName =
Diagnose.GetCurrentMachineName();
        AppSettingsAddEntry cmAsae1 = new AppSettingsAddEntry(machineNameKey, machineName);
        cmAsae1.SetValueFromEnvVar =
true;

        Entry[] entries = new Entry[] { cmAsae1 };
        return new SPwebconfigMods(entries);
    }

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        base.FeatureActivated(properties, true); // Call required for config update addition if inheriting from ConfigSPFeatureReceiver AND overriding this method

        // Do anything else you want to on Activation here

    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        base.FeatureDeactivating(properties); // Call required for config update removal if you inherit from ConfigSPFeatureReceiver AND overriding this method

        // Do anything else you want to on Deactivation here

    }
}

 

That all for now. In Part 2 I'll look a the makeup of my classes behind this, to better illustrate how to use the SharePoint config modifications yourself.

A quick update on part 2 progress:

Ryan McIntyre has also just blogged about similar things he did with this useful little class in the past, and I've been extending my solution a little also (to read/write the xml files to the feature's dir in the vs project and final 12 hive, and to read environment variables that can be pushed out by policies when the person installing the WSP needs different web.config settings per deploy). He mentions codeplex, so if others feel they might make use of a web config mods project, let us know. We'll try to put our heads together and come up with the best bits.

 

The end of another MOSSuMS post


Posted 03-18-2008 6:47 PM by Mike Stringfellow

Comments

Links (3/18/2008) « Steve Pietrek’s SharePoint Stuff wrote Links (3/18/2008) &laquo; Steve Pietrek&#8217;s SharePoint Stuff
on 03-18-2008 8:54 PM

Pingback from  Links (3/18/2008) &laquo; Steve Pietrek&#8217;s SharePoint Stuff

Mirrored Blogs wrote FeatureReceiver For Applying Custom Web.Config Changes
on 03-22-2008 6:11 PM

As I was reading through my SharePoint feeds I came across a post that struck a cord with me.&#160; The

CleverWorkarounds » "Guru of governance?" wrote CleverWorkarounds &raquo; &quot;Guru of governance?&quot;
on 04-03-2008 9:44 AM

Pingback from  CleverWorkarounds &raquo; &quot;Guru of governance?&quot;

Ryan McIntyre wrote Web.Config FeatureReceiver Update
on 07-21-2008 11:53 AM

After my previous post outlining my custom Feature Receiver used to update any section of a web.config

Suresh Meenakshisundaram wrote re: So you think you can change your Web Config?
on 11-23-2008 11:06 PM

Hi Mike,

Thank you. It is really good post. It helps me lot

Thanks,

Suresh M

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.