Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

SharePoint 2010 introduces the new UpgradeActions element to the feature manifest which allows content type (CT) lifecycle management by using the new AddContentTypeField element to add new fields to existing content types.

This is great news.

Microsoft's own MSDN documentation provides this high level walkthrough of upgrading a content type: SP2010 ALM

The guidance is as quoted:

For example, perhaps you have developed a content type to which you must add a custom site column named City. You do this in the following way:

  1. Add a new element file to the feature. This element file defines the new site column and modifies the Feature.xml file to include the element file.

  2. Update the existing definition of the content type in the existing feature element file. This update will apply to all sites where the feature is newly deployed and activated.

  3. Define the required upgrade actions for the existing sites. In this case, you must ensure that the newly added element file for the additional site column is deployed and that the new site column is associated with the existing content types. To achieve these two objectives, you add the ApplyFeatureManifests and the AddContentTypeField upgrade actions to your Feature.xml file.

In following this guidance, however, I've noted that it only correctly adds the field at the root content type and does not push it down to the list level content types. The only way I can get it to push down to the list level content type is if I do not modify the original content type to include the field. But that seems counter to step 2 in the guidance and really doesn't make sense from a lifecycle management perspective as it would mean that even new installs would need upgrades to get to the current release state.

Now here is where it gets interesting. If I do the following:

  1. Add the field to the original content type .xml
  2. Add the field to the content type
  3. Add the field to a new element manifest .xml file
  4. Update the feature.xml file to include this new element manifest .xml file
  5. Increment the version on the feature
  6. Add a new VersionRange with an AddContentTypeField and PushDown="TRUE"
  7. Upgrade the feature

At this point, as mentioned, the site level content type is upgraded correctly. However, the list level instances of this content type are NOT upgraded --- or so it seems.

Now if I go to add the column manually to the list level content type -- since it is not there by default after the upgrade, the new field will show up twice!

See screencap here: http://zaanglabs.com/_tmp/2011-05-03_112047.jpg

If I loop through the list level content type fields, indeed, it has been added twice (sorry, can't post the screen cap or link).

However, at the site level, all is well and the field only occurs once. As you can see, I've been experimenting with various scenarios and changing various parameters to see if I can get this working right.

For content type ALM to make sense, we'd want to be able to have a clean deploy and upgrade deploy in the same package. But it seems that this either isn't working as intended or I have done something wrong in setting up my upgrade.

Again, if I do not add the field to the original content type manually, the upgrade occurs successfully and the new field is added to the content type at the site and list level where it's used. However, this is counter to the guidance and it seems to be an broken way of handling ALM for content types. Any insight or experience with this would be appreciated.

share|improve this question
add comment

1 Answer

Point here is that when you modify a list, new content type is created, and old is set as parent for the new one.

The only way we found here is to run through the site lists and synchronize content types. It is not very hard to do, though.

foreach (var list in web.Lists)
{
    foreach (var listContentType in list.ContentTypes)
    {
        // featureContentTypes - is a collection of content types,
        // which this feature provisions/updates
        foreach (var webContentType in featureContentTypes)
        {
            syncContentTypes(webContentType, listContentType);
        }
    }
}

And the syncContentTypes method now will add new fields found in webContentType to listContentType:

void syncContentTypes(SPContentType webContentType, SPContentType listContentType)
{
    if (!listContentType.Id.IsChildOf(webContentType.Id))
        return;

    foreach (SPField field in webContentType.Fields)
    {
        if (!listContentType.Fields.Contains(field.Id))
        {
            // add new SPFieldLink here
        }
    }

}

MSDN referense: SPFieldLink

share|improve this answer
2  
I took a slightly different tact: http://charliedigital.com/2011/05/03/sharepoint-content-type-lifecycle-manageme‌​nt/ I found that if I simply removed and added the SPFieldLink on the content type at the root level and called Update(true), it would push down the changes. Of course, this is less than optimal as it would be great if PushDown="TRUE" worked as documented by Microsoft. –  Charles Chen May 6 '11 at 15:52
    
Thanks for sharing the link! It is a really useful knowledge :) –  Andrey Markeev May 6 '11 at 17:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.