2010, Development Blog, SharePoint
Deploying page layouts with Visual Studio to SharePoint 2010: Revert to Site Definition (Ghosting Unghosted files)
So, you are deploying branding through Visual Studio into SharePoint 2010, which includes your Masterpage(s) and Page Layout(s).
It works great the first time doesn’t it? But what then . . . as soon as you use the page layout in any of your sites, it gets locked down and can no longer be deleted and replaced.
The answer:
- CKSDEV tools and this nifty little script below. If you have never used CKSDEV tools, DO IT . . . it’s an amazing plugin for Visual Studio 2010 that will help you love SharePoint deployment.
- Set your project to Upgrade instead of the normal Default on deployment (screenshot below).
- Ghost your files after upgrade/deployment (in SharePoint Designer, this is called Reset to Site Definition) with the code below.
In your Event Receiver under FeatureActivated, add the following code.
public override void FeatureActivated(SPFeatureReceiverProperties properties) { SPSite siteCollection = (SPSite)properties.Feature.Parent; if (siteCollection != null) { SPWebCollection siteAllWebs = siteCollection.AllWebs; foreach (SPWeb site in siteAllWebs) { SPFile pageLayout = site.GetFile(site.Url + "/_catalogs/masterpage/WebpartPage.aspx"); if (pageLayout.Exists && pageLayout.CustomizedPageStatus == SPCustomizedPageStatus.Customized) { pageLayout.RevertContentStream(); } site.Dispose(); } } }
Some important things to note about this code:
- the using statement avoids memory leaks
- always check if SPAnything is null before using it – SharePoint will toss its cookies on quite a few controls if it has a null reference.
- foreach SPWeb will open every website under the current site collection, which allows you to target all sites where the masterpages and page layouts are deployed
- check if the SPFile pageLayout is SPCustomizedPageStatus.Customized
- RevertContentStream resets the file to site definition.
Sweet… Awesome… Deliciousness… Hope this helps!
3 Comments
Stephan Onisick
Have you ever had problems using a Feature Receiver deploying to a Web Application instead of the Global Assembly Cache. We have a client which we can’t deploy to the GAC.
I’m assuming WebPartPage.aspx is the layout page you want to update and RevertContentStream reads the new updated definition from the 14-hive.
thanks,
Stephan
stephan
Another Stephan! Awesome ;-D
I wrote the code above for a Sandboxed Solution so technically it should work wherever you put it (since Sandboxed Solutions are the safest solutions for SharePoint). I have to say that I’m not as familiar with Web Application deployments as I am with Site and Web deployments. The only difference that I can think of, might be how you access the current web context, so I would start there.
The 2nd part of your question: RevertContentStream actually just resets the page content to whatever is stored in SharePoint (stored in /_catalogs/masterpage/ in the SharePoint site collection, not the 14-Hive (which refers to the file system)). How this works – SharePoint stores the main (currently deployed) versions of page layouts and masterpages behind all the customized versions. If you customize a page, you’re unghosting it (customizing it) – this creates a separate version on top of the main version.
The reason this script is handy – SharePoint automatically unghosts (customizes) page layouts when they are already in use, leaving the version that was previously on the server as the one in use. If you made a change to a page layout that you want to redeploy, you have to ghost it (reset it to the server version instead of the customized version) – easy in SharePoint designer, but a nightmare if you have multiple site collections – this script resets everything to the deployed version.
Hope this helps 🙂 Let me know what you find with your deployment or if you have any other questions. Have a great day!
Stephan.