Sitecore provides you the possibility to implement your own layout resolver if the default one is not enough for you. Basically you can change the layout of a page based on a business logic without changing the item in the database.
If you can’t see the code snippets click here to switch to non-AMP mode!
How to do it?
If you are using Sitecore MVC (I hope you are using) you need to inject the following processors in the following pipelines:
<?xml version="1.0" encoding="utf-8" ?> | |
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> | |
<sitecore> | |
<pipelines> | |
<httpRequestBegin> | |
<processor type="Helix.Skeleton.Feature.CustomLayoutResolver.Processors.CustomLayoutResolver, Helix.Skeleton.Feature.CustomLayoutResolver" | |
patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel']" resolve="true"/> | |
</httpRequestBegin> | |
<mvc.buildPageDefinition> | |
<processor type="Helix.Skeleton.Feature.CustomLayoutResolver.Processors.CustomProcessXmlBasedLayoutDefinition, Helix.Skeleton.Feature.CustomLayoutResolver" | |
patch:instead="processor[@type='Sitecore.Mvc.Pipelines.Response.BuildPageDefinition.ProcessXmlBasedLayoutDefinition, Sitecore.Mvc']" resolve="true"/> | |
</mvc.buildPageDefinition> | |
</pipelines> | |
</sitecore> | |
</configuration> |
The first processor is changing the file path of the .cshtml
but unfortunately it is not enough.
namespace Helix.Skeleton.Feature.CustomLayoutResolver.Processors | |
{ | |
using Helix.Skeleton.Feature.CustomLayoutResolver.Constants; | |
using Sitecore.Data.Items; | |
using Sitecore.Pipelines.HttpRequest; | |
public class CustomLayoutResolver : Sitecore.Pipelines.HttpRequest.LayoutResolver | |
{ | |
public override void Process(HttpRequestArgs args) | |
{ | |
// CustomLayoutSettings.LayoutItemId is the ID of the new layout item in Sitecore | |
LayoutItem layoutItem = Sitecore.Context.Database.GetItem(CustomLayoutSettings.LayoutItemId); | |
Sitecore.Context.Page.FilePath = layoutItem.FilePath; | |
} | |
} | |
} |
You also need to change the layout of the context item to point to the new layout item in Sitecore.
namespace Helix.Skeleton.Feature.CustomLayoutResolver.Processors | |
{ | |
using Helix.Skeleton.Feature.CustomLayoutResolver.Constants; | |
using Sitecore.Mvc.Pipelines.Response.BuildPageDefinition; | |
using System.Collections.Generic; | |
using System.Xml.Linq; | |
public class CustomProcessXmlBasedLayoutDefinition : Sitecore.Mvc.Pipelines.Response.BuildPageDefinition.ProcessXmlBasedLayoutDefinition | |
{ | |
protected override IEnumerable<Sitecore.Mvc.Presentation.Rendering> GetRenderings(XElement layoutDefinition, BuildPageDefinitionArgs args) | |
{ | |
foreach (XElement deviceNode in layoutDefinition.Elements("d")) | |
{ | |
// change the layout ID to the new layout item ID | |
deviceNode.SetAttributeValue("l", CustomLayoutSettings.LayoutItemId); | |
} | |
return base.GetRenderings(layoutDefinition, args); | |
} | |
} | |
} |
After injecting these 2 processors you should able to change the layout of the context item in the current request. The implementation has been tested on Sitecore 8.2 update 7.