Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Experience Sitecore! | All posts tagged 'Presentation'

Experience Sitecore!

Martin Miles on Sitecore

Updating existing presentation details of base template's standard values after it has been set on derived templates

Problem: let's imagine the situation when you may have some complex template inheritance. You would like to set presentation details for each of these templates' standard values, somehow like below:

A - define layout, and header/footer common holders that will be shared for all sites (we've got a multisite setup for now)

B - define footer and header on a site level so that they remain the same within each of implemented sites 

C - define base page template that will add the rest of presentation shared between the pages (but not homepage)

Once you set presentation for standard values of A, you can go to standard values of B and see these changes, so that you add only B-specific components; the same exact story will be when you will go next to std. values of C an so on. So far, so good.

The problem occurs when you want to modify presentation coming with a base template after a derived presentation is already set. In that case, you will not see any difference, that may be seen a weird for a while. In our example, imagine you've set presentation for std. values of all three templates - A, B and then C, and then decided to add one more component to a presentation on A template (or change datasource item of existing etc.). You do changes for std. values of A, save it and as you see - these changes come into a play for template A, however, once you open B or C  they won't be there...

Explanation: let's think what in fact Standard Values are - just the default values for each of field defined in that (or parent) template. In the second case if a field has standard values for both parent and inherited template - it simply overrides parent value with inherited child's value. But, wait for a second - presentation is also stored in fields of Standard Template that all pages inherit from, how that makes possible, does it simply override?

No, for such particular cases when presentation fields are involved - override behaviour would not work at all. Let's look at our example - template A defines layout and header/footer sublayout and all that goes within __Renderings field - it's where (shared, not versioned) presentation is stored in XML-serialised format. But then, it would be overridden by setting concrete footer with no layout. Since it is the same field - it will lose layout at template B level and entire behaviour does not make any sense. To address this issue Sitecore implements a feature called Layout Deltas - so that presentation fields are not stupidly overwritten. Instead, after we defined default presentation for template A, it goes as is, as A does not have any base template with presentation set. But when setting presentation for B - it will only save the difference between itself and presentation of base template (if exists). When page is being rendered, Sitecore is wise enough to construct resulting page presentation from all the base templates only adding deltas with each derived template. That is how Layout Deltas work.

One may create multilevel presentation inheritance of standard values, appending more and more presentation on each of derived levels. However, when we want to adjust the presentation of base template (A) of current template (B) - changes will be affected only for A, but not B or C if they already have layout deltas defined. That behaviour raises questions without a doubt.

Solution: what we need to do to in order to ensure changing presentation details for A will be affected for all derived templates' items is to recourse inheritance tree of A and re-calculate layout delta for each of them with recent updates from A. In order to get this done I have re-worked a solution suggested by ... The difference is that since that time we now got a feature called Versioned Layouts, so that we need to operate both fields - __Renderings and __Final Renderings correspondingly. Apart from that I have tested it for a while and fixed few of stability issues.

Implementation: when we change presentation - we change the field, so eventually the holding item is being updated. In order to intercept this we add a pipeline processor for item:saving event:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <events>
      <event name="item:saving">
        <handler type="Sitecore.Foundation.Presentation.Services.LayoutInheritance, Sitecore.Foundation.Presentation" method="OnItemSaving"/>
      </event>
    </events>
  </sitecore>
</configuration>

And the code. I am using XmlDeltas.GetDelta() and XmlDeltas.ApplyDelta() static classes of Sitecore.Data.Fields namespace to make this work.

using System;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Events;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Data.Managers;
using Sitecore.Data.Templates;
using Sitecore.Diagnostics;
using Sitecore.Events;
using Sitecore.Globalization;
using Sitecore.SecurityModel;

namespace Sitecore.Foundation.Presentation.Services
{
    public class LayoutInheritance
    {
        public void OnItemSaving(object sender, EventArgs args)
        {
            Item item = Event.ExtractParameter(args, 0) as Item;
            PropagateLayoutChanges(item);
        }

        private void PropagateLayoutChanges(Item item)
        {
            if (StandardValuesManager.IsStandardValuesHolder(item))
            {
                Item oldItem = item.Database.GetItem(item.ID, item.Language, item.Version);

                PropagateLayoutChangesForField(item, oldItem, FieldIDs.LayoutField);
                PropagateLayoutChangesForField(item, oldItem, FieldIDs.FinalLayoutField);
            }
        }

        private void PropagateLayoutChangesForField(Item item, Item oldItem, ID layoutField)
        {
            string layout = item[layoutField];
            string oldLayout = oldItem[layoutField];

            if (layout != oldLayout)
            {
                string delta = XmlDeltas.GetDelta(layout, oldLayout);
                foreach (Template templ in TemplateManager.GetTemplate(item).GetDescendants())
                {
                    ApplyDeltaToStandardValues(templ, layoutField, delta, item.Language, item.Version, item.Database);
                }
            }
        }

        private void ApplyDeltaToStandardValues(Template template, ID layoutField, string delta, Language language, Sitecore.Data.Version version, Database database)
        {
            if (template?.StandardValueHolderId != (ID)null)
            {
                try
                {
                    Item item = ItemManager.GetItem(template.StandardValueHolderId, language, version, database, SecurityCheck.Disable);

                    if (item == null)
                    {
                        Log.Warn($"Foundation.Presentation: Item is null {template.StandardValueHolderId} in database {database.Name}", template);
                        return;
                    }

                    Field field = item.Fields[layoutField];

                    if (field == null)
                    {
                        Log.Warn($"Foundation.Presentation: Field is null in item {item.ID} in database database.Name", item);
                        return;
                    }

                    if (!field.ContainsStandardValue)
                    {
                        string newFieldValue = XmlDeltas.ApplyDelta(field.Value, delta);
                        if (newFieldValue != field.Value)
                        {
                            using (new EditContext(item))
                            {
                                LayoutField.SetFieldValue(field, newFieldValue);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Info($"Foundation.Presentation: Exception {e.Message}", e);
                    throw;
                }
            }
        }
    }
}
As I am using Helix in my development, I created a foundation module Presentation and placed the above code and config into it correspondingly. 

Hope this helps someone!

Migrating existing code to Helix. Fixing invalid dynamic placeholders

Recently I have inherited a project that utilised dynamic placeholder in a weird way:

public static HtmlString DynamicPlaceholder(this SitecoreHelper helper, string placeholderKey)
{
    if (string.IsNullOrEmpty(RenderingContext.Current.Rendering?.DataSource))
        return helper.Placeholder(placeholderKey);

    var currentRenderingId = Guid.Parse(RenderingContext.Current.Rendering.DataSource);
    return helper.Placeholder($"{placeholderKey}_{currentRenderingId}");
}

instead of more commonly used way suggested by Jason Bert:

namespace DynamicPlaceholders.Mvc.Extensions
{
	public static class SitecoreHelperExtensions
	{
		public static HtmlString DynamicPlaceholder(this SitecoreHelper helper, string placeholderName)
		{
			string text = PlaceholdersContext.Add(placeholderName, RenderingContext.Current.Rendering.UniqueId);
			return helper.Placeholder(text);
		}
	}
}

In two words, the first approach generates placeholder name using an ID of datasource item. The second approach is more traditional and is default for Helix. It was suggested by Jason Bert and also utilised by sitecore - that relies on rendering's UniqueID. In both cases, dynamic placeholders look like: /content/name-of-placeholder_017c3643-0fef-475c-95d2-bb1107beb664.

So I need to update it across entire solution. Let's iterate our items.

First of all, I do not need to go through all of item, but only those that are pages and have presentation configured, as I am going to adjust it. Secondly, those items are located under /sitecore/content folder. As many of you should know, presentation details (or deltas) for a page are kept within two fields of Standard Template - Renderings and Final Renderings that correspond to configuration you see at Shared Layout and Final Layout tabs. These thoughts resulted in using following Sitecore query to identify those items:

/sitecore/content//*[@__Renderings != '' or @__Final Renderings != '']

So far, so good. Also need to mention that I will perform the operation for master database only and for Default device:

private const string DatabaseName = "master";
private const string DefaultDeviceId = "{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}";

I am using Sitecore presentation API in order to achieve my goal. Below is my Iterate() method:

public Dictionary<Item, List<KeyValuePair<string, string>>> Iterate()
{
    var result = new Dictionary<Item, List<KeyValuePair<string, string>>>();

    var master = Factory.GetDatabase(DatabaseName);
    var items = master.SelectItems(ItemsWithPresentationDetailsQuery);

    var layoutFields = new[] {FieldIDs.LayoutField, FieldIDs.FinalLayoutField};

    foreach (var item in items)
    {
        foreach (var layoutField in layoutFields)
        {
            var changeResult = ChangeLayoutFieldForItem(item, item.Fields[layoutField]);

            if (changeResult.Any())
            {
                if (!result.ContainsKey(item))
                {
                    result.Add(item, changeResult);
                }
                else
                {
                    result[item].AddRange(changeResult);
                }
            }
        }
    }

    return result;
}

That method iterates through each item from returned from the query and calls ChangeLayoutFieldForItem for that item twice - for both presentation fields Renderings and Final Renderings.

private List<KeyValuePair<string, string>> ChangeLayoutFieldForItem(Item currentItem, Field field)
{
    var result = new List<KeyValuePair<string, string>>();

    string xml = LayoutField.GetFieldValue(field);

    if (!string.IsNullOrWhiteSpace(xml))
    {
        LayoutDefinition details = LayoutDefinition.Parse(xml);

        var device = details.GetDevice(DefaultDeviceId);
        DeviceItem deviceItem = currentItem.Database.Resources.Devices["Default"];

        RenderingReference[] renderings = currentItem.Visualization.GetRenderings(deviceItem, false);

        var datasourceGuidsToRenderingUniqueIdMap = renderings
            .Where(r => !string.IsNullOrWhiteSpace(r.Settings.DataSource))
            .Select(r => new KeyValuePair<string, string>(Guid.Parse(r.Settings.DataSource).ToString(), r.UniqueId));

        if (device?.Renderings != null)
        {
            foreach (RenderingDefinition rendering in device.Renderings)
            {
                if (!string.IsNullOrWhiteSpace(rendering.Placeholder))
                {
                    var verifiedPlaceholderKey = FixPlaceholderKey(rendering.Placeholder, datasourceGuidsToRenderingUniqueIdMap);
                    result.Add(new KeyValuePair<string, string>(rendering.Placeholder, verifiedPlaceholderKey));
                    rendering.Placeholder = verifiedPlaceholderKey;
                }
            }

            string newXml = details.ToXml();

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

    return result;
}

Further down it creates a list of matches for all the renderings within current presentation field of that particular item - datasource GUIDs matching to unique rendering IDs to go through it and do a replacement - that is done in FixPlaceholderKey method. Once everything is replaced, save the field by calling LayoutField.SetFieldValue() of course wrapping that call with EditContext as we are modifying item's field value.

FixPlaceholderKey is a simple method that just does case insensitive replacement by using Regex:

private string FixPlaceholderKey(string renderingInstancePlaceholder, IEnumerable<KeyValuePair<string, string>> map)
{
    var value = renderingInstancePlaceholder;

    foreach (var oldValue in map)
    {
        value = Regex.Replace(value, oldValue.Key, Guid.Parse(oldValue.Value).ToString(), RegexOptions.IgnoreCase);
    }

    return value;
}

That is pretty everything about the dynamic placeholder fixing logic.

But as for my case - I was aware that I'll need to run this dynamic placeholder replacements few more times in future and will likely need to implement some other similar small tools. So I decided that it would be great to place it under /sitecore/admin folder along with other admin tools - exact location by purpose! And since we're now going Helix, I decided to follow good principles and created a foundation module called AdminTools, where I will be adding similar admin folder tools. So here's how it looks for me in the Solution Explorer:


FixDynamicPlaceholders.aspx is a classical ASP.NET WebForm with one line markup (ah-h, I was so lucky not to deal with Webforms for couple past years till the moment)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FixDynamicPlaceholders.aspx.cs" Inherits="HomeServeUsa.Foundation.AdminTools.sitecore.admin.Maintenance.FixDynamicPlaceholders" %>

and the codebehind. Since FixDynamicPlaceholders.aspx is admin tool page - codebehind is inherited from Sitecore.sitecore.admin.AdminPage:

public partial class FixDynamicPlaceholders : AdminPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        var fixRenderings = new DynamicPlaceholdersModifyService();
        var result = fixRenderings.Iterate();

        OutputResult(result);
    }

    private void OutputResult(Dictionary<Item, List<KeyValuePair<string, string>>> result)
    {
        Response.ContentType = "text/html";

        Response.Write($"<h1>{result.Count} items processed</h1>");
        foreach (var pair in result)
        {
            Response.Write($"<h3>{pair.Key.Paths.FullPath}</h3>");

            foreach (var kvp in pair.Value)
            {
                if (kvp.Key != kvp.Value)
                {
                    Response.Write($"<div>{kvp.Key} ==> {kvp.Value}</div>");
                }
            }
        }
    }
}

Finally, it is complete. Hope this helps someone!

P.S. of course, that would be easier (and more elegant) to perform with Sitecore PowerShell extension. But unfortunately I am the only person in the organisation who uses it regardless of my promotional activity.

Sitecore Technical User Group UK - January 2016 - Download presentation

Yesterday I have attended Sitecore Technical User Group in London and would like to share presentations from it. There were 3 presenters, talking about:

1. "CDN with Sitecore" presented by Kamruz Jaman, a Sitecore MVP 2013-2015 and in general one of the most experiences Sitecore architect, who seems to have an answer to any question (StackOverflow). He reviewed know approaches of implementing CDN into a solution in order to reduce bandwidth and improve you servers performance, and demonstrated the most complex - integrating Azure into Sitecore with media items being directly uploaded to the cloud storage,
Download presentation (521.5KB)

2. "Continuous Integration & Delivery for Sitecore" by Jason Bert.
Jason seems to know everything about CI with Sitecore. He stated, that is absolutely doable to achieve a working CI setup with Sitecore, GIT, TeamCity and Octopus Deploy and showed us how-to. Less theory in favor of a practical demo in real-time!
Download presentation (4.4MB)

3. "Sitecore 8.1: new Features and Improvements" presented by Steve McGill.
Steve guided us through serious list of new features and improvements in Sitecore 8.1 - there are so many sweeties I am anticipationg to start working with! At the end of presentation he also discussed Sitecore Habitat - a project bringing modular approach into Sitecore.
Download presentation (2.3MB)

Steve McGill and Kamruz Jaman:


Light of knowledge is coming out of Jason Bert


Thanks to presenters and everyone who has attended!

Productivity Improvement: Device Editor showing datasource and previewing that right from a pop-up click

After previous post on Layout Details dialog improvements, I decided to look even further and implement one more improvement that came into my head.

Another dialog window, probably most important in Content Editor is missing couple things I just decided to fix. That is a case when a screenshot is better than hundred words, so here is it:


What has been added is a datasource item path, immediately underneath rendering and placeholder. It is clickable in the same manner as from previous posts, immediately opening that (datasource) item for view and edit right in the popup window, that saves so much time!

Additionally, rendering / sublayout name became also clickable with the same item preview popup effect.


Download: please get the package and anti-package to revert changes. Source code is available at GitHub page by this link.

Known minor issue: if open Control Properties dialog from Device Editor, and when you return back from that dialog - look-up links will not work and control will return to default behavior, so you may need to re-open Device Editor again.
The reason for such a behavior is that on returning back, Sitecore runs a series of pipelines that eventually call original class from Sitecore.Client rather than the one we have overridden and referenced above. Fixing that requires patching original DLL and I highly wanted to avoid inclining into any original functionality (moreover, you are not likely allowed to do that by license)

Version Layouts - what is that for?

Every good Sitecore developer is familiar with the principle of versioned and shared fields - an item can contain a mixture of both types. People often wrongly consider items are versioned (for simplicity), however in fact that is not quite true. Fields may have versions, not items. When user creates a new version of item in fact only new versions of versioned fields are created, and not the shared. This concept aims to address effectiveness of data storage and it works well and transparent to users. So far, so good.

Previously, we did not have similar feature for Presentation details - it was always shared. Saying Presentation I mean layout details for devices, renderings, placeholders etc. - everything that stored in Renderings field of Layout section of Standard Template every page should inherit from.


Final presentation for an item was merged from whatever stored in Standard values (for item's template) with Layout Delta (changes individually applied to item - a delta from those in Standard Values). Standard values were stored at Rendering field of Standard Values item for a template of that specific item, thus it was the chared for all the items of that particular template; Layout Delta was physically stored in Renderings (shared) field, but of that specific item, thus applied individually to that item.

Since Sitecore 8 - there is one more point for consideration - a version. Standard Template has been extended with one new field called Final Renderings, and what is principally important at that moment - Final Renderings is a versioned field. The point of introducing that new field was that now it becomes possible to have different presentation of a page for different languages and various versions. Also, now it is possible to have a specific version of page's presentation and have it published for a while (without creating duplicates and renaming the in real-time) - now all the information is stored withing same page item.


So, before, while building the presentation Sitecore had to consider only two Renderings fields - one from item's template's Standard values, another from item itself. As both parts were shared - resulting presentation was always the same across languages and versions. Previously if you wanted a page to look different for different laguages - you were limited to personalizing renderings by specifying languages and renderings in Rules Engine. No more personalisaion required since now!

At the moment we have following configuration, in that particular order on how final presentatin is calculated:

  1. Standard Values - Renderinds field - shared.
  2. Standard Values - Final Renderinds field - versioned.
  3. Item - Renderinds field - shared.
  4. Item - Final Renderinds field - versioned.

Here's the diagram (from official site) on how final presentation is calculated with the above bunch of sources of presentation:


Thus, important advice - do not use them four at the same time, as it may behave unpredictable. Before Sitecore 8 most popular combitaion user for presentation calculation was (1)-(3), less often just (1) or (3) solely by themselves. Now you may safely use combitations of (1)-(2)-(4) or (1)-(3)-(4), as they were tested and proved with time. Of course, previous (1)-(3) from migrated projects will work as before, until you modify and save it with Experince Editor. Experince Editor works with Final Renderings field and not with shared Renderings field.

These above were just brief notes about Versioned Layouts, I left that in blog mostly for myself to have quick access to. But if you may want to understand how Versioned Layouts work in details,I would highly recommend to read a series of articles called Version Layout - Mixed Feelings (part 1, part2 and part 3).

See also Sitecore item's extension methods for identifying version layouts (link).

Hope you find this post helpful!

Tip: copying Presentation Details manually

I came across a question on StackOverflow where a guy asked about copying presentation details and decided to share this quick tip. Saying Presentation Details I mean all the information about layouts, renderings, placeholders etc., so whatever you usually configure on that screen:



So, you usual data is stored within item's fields, but where does presentation live? Well, presentation is also kept within item, but in a slightly different location.

You page template is inherited from Standard Template, it has plenty of important fields and sections, among which there is Layout section. Let's go and see what is there. But before, open View tab ensure Standard fields is checked in order to display all sections provided by Standard Template and also check Raw values option to display actual content of the fields:


Then, scroll down to Layouts section and expand it.


Rendering field contains all presentation details, serialized into XML. So now, if you copy them 'as-is' to clipboard and insert to another item - that item will immediately same layout, all renderings in the same order, placeholders etc. You may also copy that across environments, assuming both target and source environment have those layout and renderings.


Note: if you need to copy Presentation Details just within same database, there a nice and quick solution right from the UI:


Hope this helps!