Page Layout Shenanigans

I’ve been working on a full trust SharePoint 2010 solution that uses a module to deploy some page layouts to the master page gallery and ran into an interesting scenario…

Setting the scene

I have a feature (version 1) that deploys two page layouts.

Activating the feature deployed the page layouts to the master page gallery as expected:

  • Layout1.aspx (deployed by the feature)
  • Layout2.aspx (deployed by the feature)

Then I manually uploaded an additional page layout to the master page gallery:

  • Layout1.aspx (deployed by the feature)
  • Layout2.aspx (deployed by the feature)
  • Layout3.aspx (uploaded manually)

The problem

Later I updated my feature code (version 2) to deploy an additional two page layouts called Layout3.aspx and Layout4.aspx.

The feature upgrade completed successfully and now the master page gallery contains all four page layouts as specified in version 2 of the feature:

  • Layout1.aspx (deployed by the feature)
  • Layout2.aspx (deployed by the feature)
  • Layout3.aspx (uploaded manually)
  • Layout4.aspx (deployed by the feature)

At this point the problem is that Layout3.aspx still uses the page layout that was manually uploaded (stored in the content database) and not the page layout deployed by the feature (store in the SharePoint root).

Un-ghost in the machine

My initial thought was that in order to point the list item at the page layout deployed by the feature to the SharePoint root we can un-customize the page.

Page layouts can be un-customized via the UI by going to the reset to site definition page (site actions > site settings > site actions > reset to site definition) or using code and calling the SPFile.RevertContentStream method.

Attempting to reset (un-customize) Layout3.aspx presents the following error however:

Cannot revert to the site definition version of this file. It is a custom file and is not part of the site definition.

I confirmed that Layout3.aspx had been deployed to the feature folder in the SharePoint root and it is possible to reset all the other page layouts in this way.

Digging deeper

It was time to fire up SharePoint Manager 2010 and look at the actual items in the master page gallery to determine how things work under the hood…

Looking at the page layout items in the master page gallery there are two properties of interest regarding the “customization” of pages:

The CustomizedPageStatus property is used to indicate whether an item has been customised from its definition and can be set to none, customised or uncustomized.

For Layout3.aspx this property is set to “none” whereas the working page layouts it is set to “uncustomized”.

The vti_setuppath property is set to the path of the file in the SharePoint root.

For Layout3.aspx this property was NOT set indicating that the page layout has no file in the SharePoint root.

These two properties are the reason for the exception when attempting to reset the page layout.

Now we just need to set the CustomizedPageStatus and vti_setuppath properties and we’re off to the races but as it turns out they are read-only so we need to find another way.

Solution

After the long windy road of getting here I chose to use the following technique to “repair” these properties on the Layout3.aspx page layout:

I added another upgrade (version 3 for those keeping count) to my feature:

  • Added another manifest (elementsV3.xml) to the module to deploy the same page layout with a different name (e.g. “Layout3Fix.aspx”).
  • Added a custom upgrade action that uses the SPFile.MoveTo method to replace the old Layout3.aspx with the newly deployed Layout3Fix.aspx

Upgrading the feature to version 3 will now replace the manually uploaded page layout (layout3.aspx) with the page layout from the feature. This restores the two properties discussed previously to the correct values and the page layouts now point to those deployed by the feature in the SharePoint root.

Future updates to the page layouts by solution updates will now be reflected in content pages that use these page layouts.

Advertisements