Converting dynamic placeholder keys to Sitecore 9 format with Sitecore PowerShell Extensions
Sitecore 9 supports dynamic placeholders out of the box. Unfortunately, its implementation is slightly different from existing third-party implementations for Sitecore 8, so when you try and upgrade your Sitecore 8 site to version 9, all pages that use dynamic placeholders (which might well constitute most of your site) will look empty. 😱
Richard Seal came up with a nice little Sitecore PowerShell Extensions script to convert all your existing placeholder keys to Sitecore 9 format. Unfortunately, this script doesn’t cater for nested placeholders or multiple versions/languages.
Jeroen de Groot improved on that by creating a Sitecore admin page, which correctly caters for nested placeholders and multiple languages, though not multiple versions (see also Rama Krishna Ila’s implementation).
The admin page approach is alright, but I find the Sitecore PowerShell Extensions one more flexible. Moreover, it offers extensive off-the-shelf real-time logging and reporting functionality. It’s also very efficient and you don’t have to play with Sitecore.config settings to, say, increase the
Query.MaxItems value… Also, you don’t need to rebuild or redeploy your site, should you realize you need to slightly tweak your code! 😉
For convenience’ sake, I’m going to follow almost verbatim Richard’s original explanation here.
The Fortis placeholder generation uses
placeholderKey_lowercaseRenderingId as the pattern to generate the key. This gives you keys like this:
The Sitecore implementation is very similar, but formats the GUID slightly differently and also adds a unique numerical suffix, like so:
So, the first thing you need to do will be to remove the Dynamic Placeholder binary and config patch from your solution. To achieve this, you can just uninstall the NuGet package.
You will also need to make sure that the following files are removed from your deployed Sitecore instance:
Once those files have been removed, we need to make sure that all code referencing the namespace is changed to the new Sitecore namespace. So search and remove the namespace
DynamicPlaceholders.Mvc.Extensions from your code. If you have used
@Html.Sitecore() in your Razor views, you probably already have the namespace set correctly. If not, make sure you have these namespaces added to your views Web.config:
<add namespace="Sitecore.Mvc" /> <add namespace="Sitecore.Mvc.Presentation" />
Once you have done that, most of the code should work in your Razor views… unless you have used the overload and passed in a unique key to the Fortis ones.
The real issue now is going to be your presentation in Sitecore. Since the format of the placeholder key has changed, all the existing renderings will need their placeholder keys updating, too… Hence the need for our script. 😁
So, here is my improved script, catering for all [nested] placeholders in all rendering definitions of both the shared and final layout of all versions and languages of the selected Sitecore items. Please note: I’m no PowerShell guru, so the code might not be the most efficient. Also, there is a lot of logging going on, essentially because I wanted to make sure I was capturing every placeholder on each page.
The script is interactive and at the start presents you with a dialogue box where you can choose:
- the Sitecore content node you want to apply your conversion to (this is restricted to
/sitecore/content/and its descendants: you can change that on line 95, but shouldn’t really need to);
- whether you want to apply the conversion to the placeholders contained in the selected start item itself (default:
- whether you want to apply the conversion to the placeholders contained in all descendants of the start item (default:
- whether you want to run the script in “preview mode”, where all logging and reporting will happen as normal, but no actual conversion will be performed (default:
The script logs each rendenring definition that has been processed and returns a downloadable report with the list of all the conversions made.