Search code examples
c#web-configsitecoresitecore8sitecore-mvc

Cannot change mvc layout in SiteCore 8.0 (update 3) from code


I am trying to change layout in SiteCore 8.0 (update 3) for all my pages from code behind. I am using layout resolver pipeline for it. i can debug & see changed path, but cannot get updated layout on UI. I have seen various post by googling, who are doing same thing but those are quite old (older then 2-3 yrs).

below is my layout resolver pipeline code

  public class LayoutResolver : HttpRequestProcessor
{
    public LayoutResolver()
    {
        System.Diagnostics.Trace.WriteLine("PipeLine: ctor() has been called");
    }
    /// <summary>
    /// Gets the layout for the page
    /// </summary>
    /// <param name="args"></param>
     public override void Process(HttpRequestArgs args)
    {
        System.Diagnostics.Trace.WriteLine("PipeLine: This is atleast called");
        Assert.ArgumentNotNull(args, "args");
        if (!CanProcess())
        {
            return;
        }
        Context.Page.FilePath = "/Views/Shared/BusinessLayout_Two.cshtml";
    }

    private static bool CanProcess()
    {
        return Context.Database != null
                && !IsCore(Context.Database);
    }
    private static bool IsCore(Database database)
    {
        return database.Name == Constants.CoreDatabaseName;
    }
}

EDIT : showconfig.config show my resolver register in config. SiteCoreSample.Helpers.LayoutResolver is my resolver.

<processor type="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel"/>
<processor type="SiteCoreSample.Helpers.LayoutResolver, SiteCoreSample" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.HttpRequest.TransferMvcLayout, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.Mvc.Pipelines.HttpRequest.TransferControllerRequest, Sitecore.Mvc" patch:source="Sitecore.Mvc.config"/>
<processor type="Sitecore.ExperienceEditor.Pipelines.HttpRequest.CheckDevice, Sitecore.ExperienceEditor" patch:source="Sitecore.ExperienceEditor.config"/>
<processor type="Sitecore.Pipelines.HttpRequest.PageEditorHandleNoLayout, Sitecore.ExperienceEditor" patch:source="Sitecore.ExperienceEditor.config"/>
<processor type="Sitecore.ExperienceExplorer.Business.Pipelines.HttpRequest.ExecuteRequest, Sitecore.ExperienceExplorer.Business" patch:source="Sitecore.ExperienceExplorer.config"/>

Debug screen shot


Solution

  • Since you are using MVC you need to add procesors to a different set of pipelines, the LayoutResolver pipeline you mention is only relevant for Webforms projects..

    I would suggest you create another Layout item under /sitecore/layout/Layouts for your secondary MVC layout. Then create processor that will switch the layout item to the secondary one as required:

    using System;
    using Sitecore;
    using Sitecore.Mvc.Pipelines.Response.GetPageRendering;
    
    namespace MyProject.CMS.Custom.Pipelines.GetPageRendering 
    {
        public class GetCustomLayoutRendering : GetPageRenderingProcessor
        {
            public override void Process(GetPageRenderingArgs args)
            {
                if (args.Result == null)
                    return;
    
                if (!ShouldSwitchLayout()) //or whatever your custom logic is
                    return;
    
                args.Result.LayoutId = new Guid("{guid-to-alt-layout}");
                args.Result.Renderer = null;
            }
        }
    }
    

    And the patch the processor in to the mvc.getPageRendering pipeline:

    <mvc.getPageRendering>
      <processor type="MyProject.CMS.Custom.Pipelines.GetPageRendering.GetCustomLayoutRendering, MyProject.CMS.Custom"/>
    </mvc.getPageRendering>
    

    It's important to set args.Result.Renderer to null, since that will force the rendering to be refetched and use the alternative layout from the ID you just set.