In Parts 1 and 2 of this series we covered some of the pitfalls and precautions the need to be taken when deploying SharePoint artifacts such as Site Columns, and Content Types. Wrapping up these posts we will discuss how to deploy Page Layouts successfully. And just so that we are still on the same page, these posts are focused on deploying using the SharePoint Solution deployments not creating these artifacts using SharePoint Designer or the Web Interface.
Page Layouts are a great way of reusing structure within your sites. My typical development pattern is to create a layout in a development environment using the web interface, the open it up in SharePoint Designer to polish it up.
The main reason I go about it this way is that using SPD to design a layout is just so easy. Think of it in the same vein as what Visual Studio does for regular ASP.NET applications. The astute reader may have noticed that in previous posts I have cautioned against the use of SPD. This is true, but that is always tempered with 'with caution'. Knowing what using SharePoint designer means can make all the difference. Additionally, I only use it against my development farm, no where else.
Once I have gotten the layout to a state that I am happy with, I copy the contents using the code view of SPD, paste it into a file in Visual Studio. From there I can add it to my Feature and have it deployed properly. I then reghost the file. Remember that SPD is going to unghost (customize) the file and any attempt to update it using a feature will fail miserably.
Here's your first tip: It appears that some engineer, and I use this term loosely, decided that when you deploy a file to SharePoint, the determination of it being a Page Layout is the presence of a tag with the name 'Content'. Not 'content', or 'conTent', just 'Content'. Would you care to guess what capitalization SPD uses by default for content section in page layouts? Yep, you guessed it 'content' I'm shipping a case of wet trout to the MS campus as you read this, let the slapping begin. And it gets even worse, you have to have all the <asp:Content /> controls use the proper case.
The fallout of this is that if you deploy a file without a 'Content' tag SharePoint determines that this is just a plain old HTML file, however it does some additional inspection and doesn't find an HTML tag, so it kindly inserts one for you. Isn't that sweet? I'm not smiling. This causes your layout file to be customized and and future upgrades will appear to not work even though the file in the 12 Hive is correct. Here is the offending code that you will find at the end of you page layout if you view it in SPD.
<META name="WebPartPageExpansion" content="full">
<!--[if gte mso 9]><xml>
<mso:ContentType msdt:dt="string">Page Layout</mso:ContentType>
<mso:PublishingAssociatedContentType msdt:dt="string">;#Agenda item;#0x010100C568DB52D...;#</mso:PublishingAssociatedContentType>
<title>Dummy Content Type</title></head>
Fortunately this can be easily corrected, if you've already been bit by it. You’ll know this is the problem, because when you go to load a page based on that layout, you’ll receive this error:
Only Content controls are allowed directly in a content page that contains Content controls.
First do a Find/Replace on your Page Layouts and make all of the asp:content tag asp:Content. Next using the STSADM Extensions from Gary Lapointe, uncustomize the file with the gl-reghostfile operation.
This operation uses the RevertContentStream() method of the SPFile class. Now when you upgrade your solution the updated layouts will be used.