Asymmetrical Placeholder Keys in Sitecore 7.5

UPDATE: Sitecore Support confirmed it’s a bug in the MVC pipelines in 7.5. If you are doing WebForms you should be fine with mixed case placeholder keys. There’s now a Sitecore.Support.424797.dll patch that replaces GetAllowedRenderings with a corrected version. I still believe proper fix belongs in the cache class itself – exposing the knowledge of the cache key semantics and the GetCacheKey() method logic outside the cash class’s boundaries manifests a leaky abstraction but that’s an off-topic software architecture debate.

Placeholder Settings

We all know and love placeholder settings in Sitecore. If you are new to Sitecore or are not exactly sure what is the difference between global and localized placeholder settings (important for this blog post) I recommend that you read this good article by Chris Castle:

The Power Of Placeholder Settings

Allowed Renderings

Placeholder settings control what renderings (aka components) can be used in a given placeholder on a page. You normally define it on the placeholder settings item (the Allowed Controls field). In SCORE we also have an extension that allows us to override placeholder settings via declarative rules. One way or the other, you placeholder has to have a placeholder setting that allows at least one control to be inserted into it, otherwise there’s not much you can do with it in Page Editor.

Placeholder Cache

Page Editor uses a special kind of metadata to overlay your pages with its editing features – chrome data (I have blogged about chromes before). Chrome Data is collected via the getChromeData pipeline that in turn uses getPlaceholderRenderings to read placeholder settings. Long story short, main processor in that pipeline that is of interest for today’s blog post – GetAllowedRenderings – does two things:

  • Reads your placeholder settings from the item’s layout definition if it’s defined there (localized placeholder setting)
  • Searches for a global placeholder setting with a key that matches the placeholder it runs the pipeline for

Prior to 7.5 that second step was a simple query over placeholder settings items in the /sitecore/Layout/Placeholder Settings. 7.5 introduced a new cache – Placeholder Cache. I guess querying that structure over and over again was identified as a bottleneck and it was decided to cache it. If you inspect the config on a running 7.5 instance you will find six occurrences of the new Sitecore.Caching.Placeholders.PlaceholderCacheManager that handles keeping the cache up to date upon changes to the items. The cache, of course, initializes itself lazily upon first use.

Case Matters

Do you lowercase your placeholder keys? We normally don’t. I kind of like the mixed case approach: Main vs. main, or Above Page Content vs. above page content. It reads better I guess. Alas, can’t do it in 7.5 initial release. Not with global placeholder settings.

Placeholder Cache stores placeholder settings items using the Placeholder Key value as a key. There’s one caveat though. The cache uses a conversion method to calculate the actual cache key from the value that is passed in:

    protected virtual string GetCacheKey(string key)
    {
      if (this.IsKeyCaseSensitive || string.IsNullOrEmpty(key))
        return key;
      else
        return key.ToLowerInvariant();
    }

Placeholder Cache overrides the IsKeyCaseSensitive property with:

    public override bool IsKeyCaseSensitive
    {
      get
      {
        return false;
      }
    }

That will make the actual cache key use the lowercased Placeholder Key. It all kind of makes sense, right? Main and main should probably be the same thing anyway.

The problem is, in the 7.5 initial release adding the placeholder settings item to the cache and looking it up by key are not symmetrical operations.

Here’s how a global placeholder settings item is looked up:

  PlaceholderCache placeholderCache = PlaceholderCacheManager.GetPlaceholderCache(database.Name);

  Item obj = placeholderCache[placeholderKey];

The indexer property in the cache does not use the conversion method to calculate the key to use for the lookup. The value goes straight into the TryGetValue of the inner data structure.

What do we do now?

I filed a support ticket with all the details (#425605). I believe the right way to fix is to make the two operations symmetrical and use the GetCacheKey when looking up the item from the cache. In the meantime, if you are using 7.5 initial release you are better of with lowercase placeholder keys. And if you are migrating a site from earlier versions to 7.5 you will need to change your renderings to use lowercase keys when referring to a placeholder. You don’t really need to change the Sitecore items but I would do it too. I don’t like asymmetry, especially in placeholder keys.

Pavel Veller

1 comment on Asymmetrical Placeholder Keys in Sitecore 7.5

Kevin DevereauxMay 5, 2015 - Reply

Thanks Pavel! Ran into this issue working on a 6.6 to 7.5 upgrade. Pulling in the patch took care of it.

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back