Multiple Layouts

Topics: Customizing Orchard, Writing themes
Dec 27, 2011 at 2:54 AM


I new to Orchard, but not to MVC/development.  Setting up an Azure instance and it's working pretty good, though finding a lot of modules are limited.  Modifying as needed.  So far, Orchard seems like the way to go!

I have an SEO issue though with Orchard, and it's not clear on how to change it.  I'm hoping someone here can help.

Per SEO, you are to have a different H1 per page.  Ok, no issue with that as I can modify the parts cshtml.

The problem comes from when I want to use the same header on the homepage as an H1 tag, but on all other pages the header should be an H2.  Let me give an example:

Homepage HTML:

<div id="header">
  <h1>Eric Duncan</h1>
  <li><a href="...">Title of Article 1</a></li>
  <li><a href="...">Title of Article 2</a></li>
  <li><a href="...">Title of Article 3</a></li>

And an article page:

<div id="header">
  <h2>Eric Duncan</h2>

<h1>Title of Article 1</h1>

<p>Body of content ...</p>


Notice how the Header is different between the two?  The homepage uses an H1, and all other pages will have it set as H2.

I tried to override the Layout from within the Parts, but I get a read-only error.

	Layout = "";


If there is a different way I can have the homepage use a different Layout or header, please let me know.



Dec 27, 2011 at 6:22 AM
Edited Dec 27, 2011 at 6:24 AM

Install the designer tools module, enable the url alternates feature and add a layout-url-homepgage.cshtml file to the views folder of your theme.

Dec 27, 2011 at 8:32 PM

Bertrand, if i have a custom module, what is the naming convention of the layout I should use in my theme? 


For example, my module has url's like /shoes/435682/shoe-name (similar to stackoverflow's URL format for questions, the shoe-name part is just for SEO, the ID part is the only part used for finding data). 

If i want all the /shoes/... pages to use an alternate layout, what would I name the layout in my theme? 


Thanks in advance. 

Dec 27, 2011 at 8:48 PM

There is no convention but the one you create. In that case, you should create your own alternates. For example, if those are handled from a controller or from a driver, you can get to the layout shape through the work context, and add your own alternates from there.

Dec 27, 2011 at 10:00 PM

Thanks, I'll have to read more about shapes and layouts to understand what you mean. I haven't yet seen or worked with code that does something like what you mention. 

Dec 28, 2011 at 4:36 AM

Did a a little more reading and i think i should clarify what i was asking. I want to know how to change the main Layout.cshtml to an alternate one if the request is for an url in my /shoes/... folder. I don't want an alternate layout for my custom content types. 

Dec 28, 2011 at 7:22 AM

Dec 28, 2011 at 1:54 PM
Edited Dec 28, 2011 at 1:56 PM

Thank you -- that answered my question. I first tried it exactly as your post described, got it working for one of my module's Controllers, and then modified it a little.

What I wanted was for every page to use Layout.cshtml (as happens by default), and then if the request is going to one of three specific controllers, to use an alternate layout. But I didn't want to create three copies of my alternate layout (one for each Controller that uses the alternate layout), so I defined LayoutFilter.cs like this: 

using System; 
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard;
using Orchard.Mvc.Filters;

namespace ShoeDepot.Filters
    public class LayoutFilter : FilterProvider, IResultFilter
        private readonly IWorkContextAccessor _wca;

        public LayoutFilter(IWorkContextAccessor wca) 
            _wca = wca;

        public void OnResultExecuting(ResultExecutingContext filterContext) 
            WorkContext workContext = _wca.GetContext();
            RouteValueDictionary routeValues = filterContext.RouteData.Values;
            string controller = (string) (routeValues["controller"] ?? string.Empty); 

            if (controller.Equals("Shoes", StringComparison.OrdinalIgnoreCase)
                || controller.Equals("AdvancedSearch", StringComparison.OrdinalIgnoreCase)
                || controller.Equals("Accessories", StringComparison.OrdinalIgnoreCase))

        public void OnResultExecuted(ResultExecutedContext filterContext) { }

In my theme I saved my alternate layout under /Views/Layout-LeftRight.cshtml. 


Now when a request comes in that is routed to the ShoesController, AdvancedSearchController, or AccessoriesController, Orchard uses the /MyTheme/Views/Layout-LeftRight.cshtml, and all other requests use /MyTheme/Views/Layout.cshtml.