How to preserve renderings order when upgrading from Sitecore XP 8.1 or Sitecore XP 8.2 to a later version


Description

After upgrading Sitecore XP instance to 8.2 Update-7, the order of renderings can be changed if the layout delta consists of only the p:before="" attribute. As a result, content is displayed incorrectly on the front-end site.

In previous Sitecore XP versions (8.1 Update-1 and earlier), layout delta was created and processed from top to bottom using only the p:before="" attribute.

From Sitecore XP 8.1 Update-2 to Sitecore XP 8.2 Update-6, layout delta was created and processed from top to bottom using the following set of attributes:

Starting from Sitecore XP 8.2 Update-7 (was merged into Sitecore 9.0 Update-2), the parsing logic was changed in the scope of fixing the related issue. Now layout deltas are parsed in reverse order using the set of attributes mentioned above.

Solution

To address the issue, proceed as follows:

  1. Back up the affected database.
  2. Install a clean Sitecore instance (from Sitecore XP 8.1 Update-2 to Sitecore XP 8.2 Update-6).
  3. Configure the instance to use the affected database (for example, master).
  4. Use the following code to recreate the layout deltas of the affected items. You can create an aspx page under the website root folder of the installed instance and put the code in the Page_Load method.
    //collect all the affected items (these may be all content items or items of a specific template) and use the method below for each item:
    
    public void UpdateLayoutField(Item item)
    {
      bool isSharedLayoutFieldUpdated = false;
    
      foreach (var language in item.Languages)
      {
        Item itemInLanguage = _database.GetItem(item.ID, language);
        if (itemInLanguage.Versions.Count > 0)
        {
          foreach (Item itemVersion in itemInLanguage.Versions.GetVersions())
          {
            foreach (Field f in itemVersion.Fields)
            {
              if (f.ID == FieldIDs.FinalLayoutField)
              {
                itemVersion.Editing.BeginEdit();
                string fieldValue = Sitecore.Data.Fields.LayoutField.GetFieldValue(itemVersion.Fields[FieldIDs.FinalLayoutField]);
                LayoutField.SetFieldValue(f, fieldValue);
                itemVersion.Editing.EndEdit();
              }
            }
    
            if (!isSharedLayoutFieldUpdated)
            {
              foreach (Field f in itemVersion.Fields)
              {
                if (f.ID == FieldIDs.LayoutField)
                {
                  itemVersion.Editing.BeginEdit();
                  string fieldValue = LayoutField.GetFieldValue(itemVersion.Fields[FieldIDs.LayoutField]);
                  LayoutField.SetFieldValue(f, fieldValue);
                  itemVersion.Editing.EndEdit();
    
                  isSharedLayoutFieldUpdated = true;
                }
              }
            }
          }
        }
      }
    }