allBlogsList

Sitecore Presentation Dynamically Changing Layout and Sublayouts

There are times when you need to temporarily change a Sitecore item’s layout. In our case, we had a multi-site solution which needed to have a fallback or standard presentation for cloned items that differs for each site.

We decided, for each site, to have a settings/presentation node which would hold the presentation details that would be referenced by the cloned item. We also decided that this referenced item name would match the cloned item template name. The referenced presentation item for each site will all follow the /settings/presentation/ path.

Programmatically changing an item’s presentation requires two additions to the pipeline: layout resolver and insert renderings.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/ xmlns:x="http://www.sitecore.net/xmlconfig/" >
    <sitecore>
        <pipelines>
           <httpRequestBegin>
              <processor patch:after="*[@type='Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel']" type="XCore.Web.SitecoreExtensions.Presentation.LayoutResolver, XCore.Web.SitecoreExtensions" />
           </httpRequestBegin>
           <renderLayout>
              <processor patch:after="processor[@type='Sitecore.Pipelines.RenderLayout.InsertRenderings, Sitecore.Kernel']" type="XCore.Web.SitecoreExtensions.Presentation.InsertRenderings, XCore.Web.SitecoreExtensions" />
           </renderLayout>
        </pipelines>
    <sitecore>
</configuration>

Layout Resolver

The layout resolver determines what layout (.aspx) to load. Here, we are looking at the referenced item’s .aspx path and setting it to our own.

using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;

namespace XCore.Web.SitecoreExtensions.Presentation
{
    public class LayoutResolver : HttpRequestProcessor
    {
        /// <summary>
        /// Gets the layout for the page
        /// </summary>
        /// <param name="args"></param>
        public override void Process(HttpRequestArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if (Context.Item != null && Context.Database != null)
            {
                if (Context.Item.Visualization.Layout == null)
                {
                    Item layoutItem = PresentationManager.GetReferenceLayoutItem();
                    if (layoutItem != null && layoutItem.Visualization.Layout != null)
                    {
                        Context.Page.FilePath = layoutItem.Visualization.Layout.FilePath;
                    }
                }
            }
        }
    }
}

Insert rendering

Insert rendering determines what sub layouts(.ascx) to place onto our layout.

using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Layouts;
using Sitecore.Pipelines.RenderLayout;
using System.Collections.Generic;

namespace XCore.Web.SitecoreExtensions.Presentation
{
    public class XCoreInsertRenderings: RenderLayoutProcessor
    {
        /// <summary>
        /// Adds sublayout onto the page
        /// </summary>
        /// <param name="args"></param>
        public override void Process(RenderLayoutArgs args)
        {
            if (Context.Item != null)
            {
                if (Context.Item.Visualization.Layout == null)
                {
                    Item layoutItem = PresentationManager.GetReferenceLayoutItem();
                    if (layoutItem != null)
                    {
                        IEnumerable renderingReferences =
                            layoutItem.Visualization.GetRenderings(Context.Device, true);
                        foreach (var rendering in renderingReferences)
                        {
                            Context.Page.AddRendering(rendering);
                        }
                    }
                }
            }
        }
    }
}

Logic to grab the referenced item. Each site will each have its referenced presentation item follow the /settings/presentation/ path.

using Sitecore;
using Sitecore.Data.Items;

namespace XCore.Web.SitecoreExtensions.Presentation
{
    public class PresentationManager
    {
        /// <summary>
        /// Gets the reference layout item depending on the template name
        /// </summary>
        /// <returns></returns>
        public static Item GetReferenceLayoutItem()
        {
            string templateName = Context.Item.TemplateName.ToLowerInvariant();
            string presentationItemPath = string.Format("{0}{1}{2}",
                Context.Site.RootPath,
                "/settings/presentation/",
                templateName);
            return Context.Database.GetItem(presentationItemPath);
        }
    }
}