Wednesday, May 29, 2013

Programmatically updating Rendering datasource

I've recently discovered an undocumented feature of Sitecore and decided to share my experience.

The task at hand was to import data from a thrid party system into Sitecore generating items based on specific template. In the standard values of that template I had a few MVC renderings (views) assigned. A lot of those renderings had to have datasource set to be pointing either to the newly created item for imported record or to a child of that item. Updating datasource for all assigned in SV renderings turned out to be not so straight forward task. The first thing I attempted is to update Datasource property on each rendering, which turned out to be a wrong decision. Updating this property makes Layout Details windows to display duplicate renderings, even though there are none. You don't have duplicates, but each rendering has two different values if you look at the raw value of the layout field. Needless to say that rendering engine had issues with processing this value as well. What I ended up doing is not updating Datasource property, but one of DynamicProperties called "s:ds". Surprisingly, when you update it's value, system also updates Datasource property and everything starts magically working. Here is what I ended up doing:

LayoutDefinition layout = LayoutDefinition.Parse(bioItem[Sitecore.FieldIDs.LayoutField]);

foreach (DeviceDefinition device in layout.Devices) {
   if (device.Renderings != null) { 
      for(var i =0; i < device.Renderings.Count;i++) { 
         RenderingDefinition rendering = (RenderingDefinition)device.Renderings[i];     
         if (rendering.ItemID == renderingId) { 
            //rendering.Datasource = renderingDatasource;  // creates duplicates rendering in the layout details window.  
            rendering.DynamicProperties.Where(p => p.Name == "s:ds").ToList().ForEach(p => p.Value = datasource); 
         } 
      } 
   }