Propagating Content Type Changes in MOSS 2007

First, a short intro - I'm starting this blog for 2 reasons - 1, I'm learning a lot of stuff right now that if not used regularly, I'll forget - and need a quick way to document some of it, and 2, if it weren't for the other people out there doing the same, I wouldn't have learned a lot of what I have. So hopefully my experiences will help someone else out there, too.

Now, on to the good stuff. The problem I've been tackling this week is in MOSS 2007 - specifically, the deployment and propagation of Content Types in an enterprise environment, using the Features & Solutions Framework. Here's the background:

  1. MOSS is being used as a publishing platform for a very large project. (Hundreds of thousands of webs).
  2. Following best practices for enterprise MOSS architecture, Content Types are being deployed through Features, and are inherited by pages (list items) in subwebs.

The challenge is that MOSS really doesn't support updates to content types through the Features & Solutions framework (i.e., you are using XML Based Content Types). Once you've deployed your feature, it's going to be a little bit of a fight to update a content type by upgrading the solution. On the other hand, MOSS's editing capabilities of content types through the UI works extremely well. So, my goal has been to come up with a way to replicate the "UI" behavior within the confines of the Features & Solutions framework.

The first thing I discovered is that if you Deactivate your feature, Retract it, Delete it, Install it, Deploy it, and Activate your feature again, new fields that you've added to the Content Type in XML do, in fact, appear. The only problem is, everything that inherits from that Content Type (let's say, oh, a few million list items?) does not see any of the changes. This is because a new "list" Content Type is created any time you assign a content type to a list, and the new List Content Type inherits from the "real" one that you deployed through your feature. Soren Nielsen describes this briefly in his blog post.

So, at this point, the problem that still remains is that we need a way to propagate changes from a Parent Content Type down to its Child Content Types (in this case, pages in a publishing web that inherit from it). Microsoft's MSDN article on Updating Child Content Types pretty much spells this out for us:

"You cannot add columns to an existing site content type declaratively, in other words, by updating the Feature XML files."

Unfortunately, we simply can't create a business requirement in an enterprise MOSS installation that says "once we deploy content types, they can never change."

There are a few blogs out there that have proposed the same solution, as well as a Microsoft engineer that worked with me on this issue - use the MOSS Object Model to recurse individually through each subweb, check each list, compare fields, and programmatically add the field links that don't exist. Some have even integrated this into a STSADM command. I gave this a shot, and it takes between 0.2 - 0.4 seconds to check and compare fields on a list item. This may not sound like a lot (and will work fine for a smaller MOSS install), but for this particular environment, this technique would take at least 66 hours (2.7 days) to propagate Content Type fields.

You may notice, though, that MOSS 2007 out of the box has a special little radio button in the UI where you add a new column to a content type - "Update all content types that inherit from this content type" (yes/no). Propagating new columns/fields this way works dramatically faster - about 0.04 seconds per WEB. This is much more acceptable.

Kicking this around with a team member, we eventually understood what MOSS was actually doing. MOSS, out of the box, during a Content Type update, creates a list of changes to a content type, and then will propagate those changes via the SPContentType.Update() method. The cool thing, is that .Update() takes an optional boolean parameter - "UpdateChildren". This will propagate the current set of changes to child content types (which in our case are lists). Tested it, and it works! Essentially, there's no way to make the Features & Solutions framework call .Update(true) - if we can find a way to do this, we have our solution.

At the end of the day, we need to update the Content Type XML files, but programmatically add or make changes to the fields ourselves in the Object Model. So I've modified the steps to deploy a solution with a small utility to go along with it. Here is the procedure:

  1. Upgrade the revised solution in-place (no deactivating features). At this point you will NOT see any new fields/columns in the content type.
  2. Compare the fields in your revised solution (WSP) file with the fields and field links that currently exist in your "Live" Content Type as it currently exists in the MOSS farm. I wrote a utility to accomplish this by extracting and parsing the contents of the WSP package and make a class model of the fields.
  3. For any fields that don't exist, create the field (SPField) and add a field link (SPFieldLink) to the Content Type.
  4. Call SPContentType.Update(true).

As long as you can make field/column changes programmatically and .Update(true) them in one shot, MOSS does the rest (and much faster than enumerating through every list).

  • Got a pingback on this (glad you liked my post).

    Sounds interesting. Care to share the code?

    I'm planning to do this too through some feature receivers that compares the given xml file with the existing content type and performs all updates through code.
    Very similar to yours, though it sounds like you made an external tool (?)

    Regards
    Søren

    • brandonpotter

      This is going through testing right now... as soon as this looks solid (and it looks like it's headed that direction!) I'll see if I can post the code for it!

  • Richard

    Hi Brandon, I was reading Soren's blog, and ended up here. It sounds like a great solution, and I would be very interested in this code as well, if you do decide to share it.

    Thanks in advance.

    Regards

    Richard

  • Any news on you got it to be stable?
    And do you have posted the sourcecode?

  • Pingback: ()

  • Your style is unique compared to other folks I have read stuff from.

    I appreciate you for posting when you have the opportunity, Guess I'll just bookmark this blog.