Six tips when deploying SharePoint 2013 masterpages, page layouts and display templates

Posted by Rik Hepworth on Monday, February 3, 2014

I’ve been hat-swapping again since just before christmas (which explains the lack of Azure IaaS posts I’m afraid). I’ve been working on a large SharePoint 2013 project, most lately on customising a number of elements around publishing. Getting those custom elements into SharePoint from my solution raised a number of little snags, most of which were solved by the great internet hive mind. It took me a long time to find some of those fixes, however, so I thought I’d collect them here and reference the original posts where appropriate.

1. Overwrite existing files reliably

This has long been an old chestnut for as long as I have been working in SharePoint. Your solution deploys a file to the masterpage gallery or style library. You deploy an updated version and none of your changes are visible because SharePoint hasn’t replace the file with your new version. In previous versions careful use of things like ‘ghostable’ in library in the elements.xml when you deployed the file helped – files that are ghostable generally seem to be updated, unless you manually edit the file, thus ‘unghosting’ it.

In SharePoint 2013, however, we appear to have a new property that we can specify in our elements.xml for deployable files, ReplaceContent:

<File Path="myfile.aspx" Url="myfile.aspx" Type="GhostableInLibrary" ReplaceContent="TRUE" />

As far as I can tell, this does what it says on the tin. Overwrites existing files by default.

2. Provision Web Parts into page layouts safely as part of a feature

This is one I’d never personally tried before. I’ve seen many people struggling, pasting web part code into a masterpage or page layout and having problems during deployment. The way to do it (the ‘right’ way as far as I can know) is to use the feature to do it. When you list your masterpage or page layout in the elements.xml you can add a property that deploys a web part, AllUsersWebPart:

<File Path="myfile.aspx" Url="myfile.aspx" Type="GhostableInLibrary" ReplaceContent="TRUE" >  
<AllUsersWebPart WebPartZoneID=”TopZone” WebPartOrder=”0”>  
<![CDATA[  
]]>  
</AllUsersWebPart>

Simply specify the name of the web part zone in your page and it will be added during the deploy. The webpartorder setting should allow you to define where it appears. When adding multiple webparts I have had more success setting that to zero for each web part and just getting the order right. As you might have guessed, for multiple web parts, add multiple AllUsersWebPart sections.

But where’s the web part, I hear you cry! In that CDATA block, paste the XML for your web part. Getting that is easy – simply export the web part from SharePoint and paste the resulting XML straight in there. There are a couple of tweaks you may need to apply that I’ll list next.

3. Substitute ~ for ~ in paths within web parts in CDATA blocks

This one stumped me for a while and I was fortunate to come across a post by Chris O’Brien that solved it for me. I was trying to add a custom Content By Search web part to a page. That web part had custom control and display templates specified, which reference the current site collection in their path (~sitecollection/_catalogs). The problem is that the tilda gets stripped out by SharePoint when the page is deployed, breaking the setting.

The solution turns out to be one of those typical off the wall ‘I would never have thought of that!’ solutions that crop up all the time with SharePoint: Swap the ~ character for it’s XML entity reference: ~.

<property name="GroupTemplateId" type="string">~sitecollection/_catalogs/masterpage/Display Templates/Content Web Parts/MyTemplate.js</property>

4. Use to include content in the Content Editor web part in CDATA blocks

Export a Content Editor web part and you will see that the HTML content that is displayed within it is in the Content element, wrapped in a CDATA block. The problem is that when deploying this web part into the page using the technique above you can’t nest a CDATA block within a CDATA block.

The solution? Change the CDATA wrapper to be the element. The snag? I have found that I need to swap the < and > symbols for their HTML entity counterparts: < and >.

<Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><value>&lt;h2&gt;?My Content&lt;/h2&gt;</value></Content>

5. Provision Search Display Templates as draft and publish them with a feature receiver

This one is a bit contentious, as far as I can tell. I derived my (simple) approach from an article by Waldek Mastykarz. The crux of the matter is this: You can either edit the HTML part of a search display template or the javascript. The ‘correct’ way is another matter though. If you have publishing features enabled then when you save and publish the HTML file, SharePoint generates the javascript file with a triggered event receiver. If you don’t have publishing enabled, as far as I can tell only the javascript files are there and the event receiver doesn’t appear to be enabled.

So… which way to jump? Well, in my case I am creating customisations that depend on publishing features, so I decided to deploy just the HTML file and let SharePoint generate the javascript. If I needed to use these things without publishing I may have extracted the javascript from my development sharepoint and deployed that.

The first part to my simple approach is to deploy the files as draft using the options available to me in elements.xml:

<File Path="MyTemplate.html" Url="MyTemplate.html" Type="GhostableInLibrary" Level="Draft" ReplaceContent="TRUE" />

I then use a fairly simple function that is called by the feature receiver on activition, once per file:

public static void CheckInFile(SPWeb web, string fileUrl)  
{  
  // get the file  
  SPFile file = web.GetFile(fileUrl);  
  // depending on the settings of the parent document library we may need to check in and/or (publish or approve) the file  
  if (file.Level == SPFileLevel.Checkout) file.CheckIn("", SPCheckinType.MajorCheckIn);  
  if (file.Level == SPFileLevel.Draft)  
  {  
    if (file.DocumentLibrary.EnableModeration) file.Approve("");  
    else file.Publish("");  
    }  
}

If you look at the original article, the solution suggested by Waldek is jolly clever, but much cleverer that I needed for a couple of display templates.

6. Make your masterpages appear in ‘Change the look’ with a preview file

In the new SharePoint 2013 world site admins have a great deal of flexibility over how their site looks. I wanted to enable users of my custom masterpages to continue to use the theming engine – selecting their own colours and fonts – but to keep the custom masterpage I had built. Again, it’s actually really easy. Simply deploy a .preview file with the same name as your masterpage (e.g. mymaster.master and mymaster.preview). The .preview is actually a clever combination od setting, html and css that allows you to specify the default colour pallete file (.spcolor) and font file (.spfont) as well as draw a little preview of your page. I was lucky on that last one, as my look was the same as the default, so I simply copied seattle.preview.

I could go a step further in that I can create a Composed Look that would show my layout as a tile in the Change My Look UI, but that involves adding items to a SharePoint list and was more than I needed for this particular project. I will need to do that for my next one, however…