Sitecore Blog: @sitecorejohn blog

Programmatically Update Layout Details with the Sitecore ASP.NET CMS

By John West, September 18, 2011 | Rating:  | Comments (3)

The How to programmatically change settings listed under the presentation tab (eg, Layout Details) thread on the Sitecore Developer Network (SDNforums prompted me to write this blog post about updating layout details using the Sitecore ASP.NET CMS.

Layout details specify the layouts, sublayouts and renderings to use for various types of device archetypes that access a web site built with Sitecore. For more information about layout details, layouts, sublayouts, renderings and devices, see the Presentation Component Reference on SDN.

Sitecore manages layout details as an XML value in the __Renderings field (*NOT* the legacy __Renderers field) in the Layout section defined by the standard template (Sitecore.FieldIDs.LayoutField). For more information about the standard template, see the Data Definition Reference on SDN.

Because layout details reference layouts, sublayouts, and renderings by GUID, you might be able to perform your update with a simple search and replace:

Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master"); 
Sitecore.Data.Items.Item item = master.GetItem("/sitecore/content/home"); 
  
if (item.Fields[Sitecore.FieldIDs.LayoutField].ContainsStandardValue 
  && item.Template.StandardValues != null) 
{ 
  item = item.Template.StandardValues; 
} 
  
string xml = item[Sitecore.FieldIDs.LayoutField]; 
const string replaceThis = "{828ADAAC-D040-484C-8634-CA9CDF51C510}"; 
const string withThat = "{DC7AD9D7-62E6-4F5C-B0EF-91103622B4B0}"; 
  
if (xml.Contains(replaceThis)) 
{ 
  using (new Sitecore.Data.Items.EditContext(item)) 
  { 
    item[Sitecore.FieldIDs.LayoutField] = xml.Replace(replaceThis, withThat); 
  } 
}

Otherwise, you can use the the Sitecore.Layouts.LayoutDefinition class and the classes that it exposes (thanks again to @techphoria414 for the original code in the SDN forum thread Data Source as GUID vs Path):

Sitecore.Layouts.LayoutDefinition layout = 
  Sitecore.Layouts.LayoutDefinition.Parse(item[Sitecore.FieldIDs.LayoutField]); 
bool updated = false; 
  
for (int i = 0; i < layout.Devices.Count; i++) 
{ 
  Sitecore.Layouts.DeviceDefinition device = 
    layout.Devices[i] as Sitecore.Layouts.DeviceDefinition; 
  
  if (device != null && device.Layout == replaceThis) 
  { 
    device.Layout = withThat; 
    updated = true; 
  } 
  
  for (int j = 0; j < device.Renderings.Count; j++) 
  { 
    Sitecore.Layouts.RenderingDefinition rendering =  
      device.Renderings[j] as Sitecore.Layouts.RenderingDefinition; 
  
    if (rendering != null && rendering.ItemID == replaceThis) 
    { 
      rendering.ItemID = withThat; 
      updated = true; 
    } 
  } 
} 
  
if (updated) 
{ 
  using (new Sitecore.Data.Items.EditContext(item)) 
  { 
    item[Sitecore.FieldIDs.LayoutField] = layout.ToXml(); 
  } 
}

As Nick notes in the first forum thread referenced, and as I failed to do in my speculative response on that thread, be sure to save the XML back to the item.

Note that this code runs in the security context of the context user and does not include any error control. Also note that updating standard values is specifically complicated by layout standard values, clones, and layout deltas. At the very least, you might want to refer to update item.Template.StandardValues rather than items under /sitecore/content. For more information about standard values, see the Data Definition Reference on SDN. For more information about clones, see my blog post Sitecore CMS 6.4 Cloning. For more information about layout deltas, see the Presentation Component Reference on SDN and Adam Conn's blog post Layout Deltas What Ifs.

Tags: API, Architecture

Comments

  • John,

    When you put the XML back into the item, you should utilize the LayoutField class. Otherwise, as I understand it, you will put the full XML into the field, rather than the layout delta.

    LayoutField layoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);
    layoutField.Value = layout.ToXml();

    The LayoutField class contains logic to compare the "set" XML with what's in Standard Values, and generate a delta.

    Nick / techphoria414

    - Nick Wesselman
    September 19, 2011 at 7:20 AM

  • @Nick: Very important distinction. I think most people would more commonly want layout deltas than layout details. It seemed to complicated for me to test for the blog post (conditions like an item containing a layout delta based on standard values that are a layout delta of other standard values, through any number of levels), but it sounds like you've confirmed that the approach you describe works.

    - John West
    September 19, 2011 at 9:17 AM

  • http://briancaos.wordpress.com/2013/09/30/merge-sitecore-layout-details-using-xmldeltas/

    - John West
    September 30, 2013 at 9:36 AM

*{0} must be filled in.
*{0} must be filled in.
*{0} must be filled in.
Newsletter

Enter your email address to see subscription options or manage your existing account

Hudson Health Plan | Read Case Study >

Our intranet has improved efficiencies in our internal communications, improved the quality of the employee experience, and gone a long way to support an improved morale among employees.

- Ted Herman, Hudson Health Plan