Fix invalid dynamic placeholders after upgrading to Sitecore 9

Sitecore 9 supports Dynamic Placeholders OOTB and does no longer require the popular Dynamic Placeholder third party module. The format used by Sitecore for the dynamic placeholders is different than the format used by the Dynamic Placeholder module:

Old dynamic placeholder pattern: placeholderName_renderingId. Example:


Sitecore placeholder pattern: {placeholder key}-{rendering unique suffix}-{unique suffix within rendering}. Example:


You will have to update your presentation details for these differences otherwise the renderings will not be shown on the page.

Richard Seal already wrote a great blog post about how to upgrade this using SPE. This works well and also does a great job of explaining other tasks that need to be performed to move to Sitecore’s dynamic placeholders. However it doesn’t cover below 2 scenario’s:

  • Nested Dynamic placeholder: a rendering with a dynamic placeholder can contain another rendering with a dynamic placeholder.
  • Multilingual: a item can have dynamic placeholders in multiple language versions of the final layout.


I started with Martin Miles’ code which iterates through all the renderings and updates placeholders. From here the logic is updated to loop through each language version of every item. Below code updates every match of an old style dynamic placeholder so nested placeholders are taken care of appropriately:

bool requiresUpdate = false;

foreach (RenderingDefinition rendering in device.Renderings)
    if (!string.IsNullOrWhiteSpace(rendering.Placeholder))
        var newPlaceholder = rendering.Placeholder;
        foreach (Match match in Regex.Matches(newPlaceholder, PlaceholderRegex, RegexOptions.IgnoreCase))
            var renderingId = match.Value;
            var newRenderingId = "-{" + renderingId.ToUpper().Substring(1) + "}-0";

            newPlaceholder = newPlaceholder.Replace(match.Value, newRenderingId);

            requiresUpdate = true;

        result.Add(new KeyValuePair<string, string>(rendering.Placeholder, newPlaceholder));
        rendering.Placeholder = newPlaceholder;

if (requiresUpdate)
    string newXml = details.ToXml();

    using (new EditContext(currentItem))
        LayoutField.SetFieldValue(field, newXml);

Working Solution

The final working solution is uploaded to my Github and can be found here A few notes on solution:

  • Admin page is added at <sitecoreurl>/sitecore/admin/custom/migratedp.aspx
  • All content under /sitecore/content is updated, template standard values are not
  • Make sure to back up content before running this



2 thoughts on “Fix invalid dynamic placeholders after upgrading to Sitecore 9

  1. Nick

    I’ve added the dll files to the bin folder, the aspx page and code behind to the sitecore/admin/custom folder and gone to the url which shows 1891 items updated, but the changes aren’t reflected in the content tree or the website.

    I don’t think I’ve missed any steps. Any advice would be apprectiated.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s