Monday, 2 August 2010

Feature upgrade (part 4) – advanced scenarios

In this article series:

  1. Feature upgrade (part 1) – fundamentals
  2. Feature upgrade (part 2) – a sample to play with
  3. Feature upgrade (part 3) – introducing SPFeatureUpgrade kit
  4. Feature upgrade (part 4) – advanced scenarios (this article)
  5. Feature upgrade (part 5) – using PowerShell to upgrade Features

If you’ve been following this series you should hopefully be familiar with SP2010 Feature upgrade by now, conceptually at least. As you start to use this capability for real, it will quickly become clear that there are some interesting scenarios where it’s difficult to know for sure what would happen. I’ll document some examples that I’ve become aware of already in this post, but will also come back and add further cases as I come across them – kinda like a ‘Feature upgrade FAQ’ of sorts. I don’t have too many of these at the moment, but I wanted to share what I know now rather than wait for a longer list to materialize – if you have a scenario in mind that you’d like checked out, by all means leave a comment and I’ll look into it.

Here’s what I have so far:

Question: What happens if multiple VersionRange elements match my Feature instance version?

Consider the case where we have a Feature instance (N.B. this means a particular instance of a Feature on a particular web, site or web app - depending on the scope in the Feature definition) at version 1.0.0.0, and we apply the following upgrade instructions to it:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/" Version="3.0.0.0">
  <UpgradeActions>
    <VersionRange BeginVersion="1.0.0.0" EndVersion="1.9.9.9">
        ...
    </VersionRange>
    <VersionRange BeginVersion="1.0.0.0" EndVersion="2.9.9.9">
        ...
    </VersionRange>
  </UpgradeActions>
</Feature>

Answer: Since both of the VersionRange elements match, what happens? The answer is that both VersionRange elements will be processed against the Feature, in the order they are defined in the file. Any instructions within the VersionRange elements will be processed, be they declarative or imperative via CustomUpgradeAction. This is probably the behavior you’d expect, but it’s good to know. [P.S. Special thanks to Gary Yeoman (Combined Knowledge instructor) for winning the bet and bottoming this one out before I managed to get to it :)]

Impact: What this means is that if you have ‘overlapping’ VersionRange elements like this, you might need to plan for the fact that both sets of upgrade actions will execute for Feature instances caught by the ranges. This could be in contrast to other Feature instances across the farm which are at say, 2.0.0.0, and therefore would only be caught by the second VersionRange. Would both sets of Feature instances be in the right ‘state’ to upgrade successfully? Are we removing anything in the first VersionRange (e.g. a content type) which is used in the second VersionRange? Clearly this depends on what you’re doing, but is worth considering if you do overlap.


Question: What happens if a Feature which has been upgraded several times is activated for the first time on a site/web?

Consider the case where you have a web-scoped Feature which has been upgraded a few times to (for example) version 3.0.0.0 across all of the webs which currently exist. What happens if you create a brand new web at this point? Are all the upgrade steps executed when the Feature is activated there?

Answer: No – since activation and upgrade are different actions. However, note that some declarative provisioning will happen, since Visual Studio adds element manifest links in two places in the Feature manifest.xml file. Specifically, if you add a new element manifest during a Feature upgrade (e.g. to provision some new fields/content types/modules etc.), Visual Studio adds this into the UpgradeActions/VersionRange/ApplyElementManifests section but also into the good old-fashioned ElementManifests section too – you can see this by looking at the preview of the generated file. Of course, the latter section is what SharePoint Features have always used in Feature activation, meaning that any artifacts in the referenced elements file will be provisioned on both initial activation and subsequent upgrade. Note this only applies to elements files - other declarative steps such as AddContentTypeField and MapFile are specific only to upgrade, and the same applies to imperative steps linked with CustomUpgradeAction.

Impact: Features must be designed carefully to deal with the fact that Feature instances can have varying lifecycles. Since a new Feature is given a version number of 0.0.0.0, one option may be to use overlapping VersionRange elements (as described above) which always start at 0.0.0.0, and then immediately upgrade the Feature(s) when a new site/web is created in our scenario. Otherwise, if you are upgrading Features using AddContentTypeField or CustomUpgradeAction, it may be necessary to ensure the same steps happen on activation also – for example by ensuring the same code is called in FeatureUpgrading and FeatureActivated. This is a good illustration of some of the complexities around Feature lifecycles.
   

Question:  Do Feature activation dependencies affect the order in which Feature instances are upgraded?

Answer: Yes – any depended on Features will be upgraded before dependent Features.

Impact: It should be possible to reference ‘parent’ artifacts which are provisioned in the same Feature upgrade cycle in dependent Features. For example, if a Feature upgrade provisions a field, dependent Features would be able to reference that same field because it would exist by the time their upgrade executes.

Summary

This post outlines some considerations around Feature upgrade and ALM in SharePoint, and (probably!) concludes my series on this topic. If you’re interested in hearing more on this I have a chapter in Real World SharePoint 2010 (“the SharePoint MVP book”), where I discuss this and related topics - coverage there includes things like versioning assemblies in SharePoint 2010 development and recommendations for assembly/versioning strategies.

P.S. I’d love to hear any interesting Feature upgrade scenarios for me to test out to add to the list!

7 comments:

Anders Rask said...

Great article.
Regarding feature activation dependencies, i seem to remember when i wrote my feature upgrade article for DIWUG emagazine, that if i just iterated all features given from QueryFeatures() and a feature was dependent on another, this would throw an exception when i called upgrade on it. I will have to check tho...

Cornelius J. van Dyk said...

Excellent article Chris. We are in the middle of a major content migration and the topics of upgrading Features came up. Thanks for taking the time to put this on paper.

Unknown said...

Thanks Chris !! The first topic on this page is the exact problem I have been dwelling over for past 3 days ! :)

Chris O'Brien said...

@Pallavi,

Cool, glad it was useful! You know where I am if you have other questions :)

Chris.

Wouter van Vugt said...

Hi Jeremy,

note that the version range is exclusive for the endVersion attribute. E.g. don't specify 1.9.9.9 but specify 2.0.0.0. This makes sense, because 1.9.9.9 is not a good value. 1.9999999.9999999.9999999.99999999 would be, but that doesn't make sense. Luckily the end version is exclusive, as you can verify in MS code:

internal static bool InRange(SPVersionRange range, Version version)
{
return (((range == null) || (null == version)) || (((null == range.BeginVersion) || (range.BeginVersion <= version)) && ((null == range.EndVersion) || (range.EndVersion > version))));
}


Hope it helps,

Wouter

Wouter van Vugt said...

And did I just call you Jeremy Chris?

Chris O'Brien said...

@Wouter,

Thanks for the clarification. Waldek actually raised this with me a while back, but I still hadn't had chance to check. I believe you both though, so thanks!

Jeremy (and Chris).