Nested Layout Pages with Razor

Razor Layout pages are the equivalent to MasterPages in ASP.NET Web Forms and the Web Forms View Engine within ASP.NET MVC. Just as it is possible to nest MasterPages, it is also possible to nest Razor Layout pages. This article explores the process required to achieve nesting of Layout pages using the Razor View Engine in MVC 3, or WebMatrix Web Pages sites.

You would consider using nested layout pages if you were building a corporate site for a global company, for instance, which is comprised on many divisions, each having their own look and feel. There may be a common look and feel for the header and footer of the site, but the navigation and content changes in both structure and appearance depending on which division of the company is being featured. The imaginary company that the sample site relates to has a number of divisions, one of which is Automation and another for Electronics. Each of them has their own branding which needs ot be catered for. For simplicity's sake the following walkthrough illustrates the use of Razor in a Web Pages site built using WebMatrix, but the principals are exactly the same if you are using ASP.NET MVC 3.

Step 1

Create a new site using the Empty Site template and name this Nested Layouts. Add two folders to the site – one called Content and the other called Shared. Add a new CSS file to Content and leave it with the default file name of StyleSheet.css. Add the following code to it:

body {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 80%;
    padding: 0;
    margin: 0;
}

h1{
    color: #0093c0;
}

#wrapper{
    background-color: #c1dfde;
    padding: 10px;
    width: 800px;
    margin: auto;
    min-height: 600px;
}

#electronics, #automation{
    min-height: 400px;
}

#electronics{
    background-color: #8ec1da;
    width: 650px;
    float: left;
}

#automation{
    background-color: #ffe8d3;
}

#electronicsnav{
    background-color: #fff;
    min-height: 400px;
    width: 150px;
    float: left;
}

#automationnav{
    background-color: #dedede;
}

#automation h3{
    color: #997d63;
}

Step 2

Add a CSHTML file to the Shared folder and name it _MainLayout.cshtml.  Change the existing code so that it looks like this:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@Page.Title</title>
        <link href="@Href("~/Content/StyleSheet.css")" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div id="wrapper">
            <div id="header"><h1>Global Enterprises</h1></div>
            <div id="nav">
                <a href="Home">Home</a> | 
                <a href="About">About</a> |
                <a href="Engineering">Engineering</a> |
                <a href="Electronics">Electronics</a> |
                <a href="Automation">Automation</a> |
                <a href="Contact">Corporate</a> |
                <a href="Contact">Contact Us</a>
            </div>
                @RenderBody()
        </div>
    </body>
</html>

Step 3

Add another CSHTML file to the Shared folder and name this one _AutomationLayout.cshtml. Replace the existing code with this:

@{
    Layout = "~/Shared/_MainLayout.cshtml";
}
<div id="automationnav">
    <a href="Products">Products</a> | 
    <a href="Services">Services</a> |
    <a href="Support">Support</a> |
    <a href="Team">The Team</a> |
</div>
<div id="automation">
    @RenderBody()
</div>
<div id="footer">The Automation Division Footer</div>

Step 4

Now add a third CSHTML file to the Shared folder. Name it _ElectronicsLayout.cshtml, delete the existing code and add the following:

@{
    Layout = "~/Shared/_MainLayout.cshtml";
}
<div id="electronicsnav">
    <a href="Products">Products</a> <br /> 
    <a href="Services">Services</a> <br />
    <a href="Support">Support</a> <br />
    <a href="Team">The Team</a> <br />
</div>
<div id="electronics">
    @RenderBody()
</div>
<div id="footer">The Electronics Division Footer</div>

Step 5

Add a CSHTML file to the root folder. Name this one Automation.cshtml and replace the existing code with this:

@{
    Layout = "~/Shared/_AutomationLayout.cshtml";
    Page.Title = "Automation";
}
<h3>Automation Home Page</h3>

Step 6

Finally, add another CSHTML file to the root folder and call it Electronics.cshtml. Replace the existing code with the following:

@{
    Layout = "~/Shared/_ElectronicsLayout.cshtml";
    Page.Title = "Electronics";
}
<h3>Electronics Home Page</h3>

Making sure that the Electronics page is selected in the left pane, click the Run button to launch the page in your browser. Notice that the second navigation has a white background and the main area has a blue background. Click the Automation link in the top navigation. See how the colours change? The main content is a brownish-pink colour as is the secondary navigation. The heading in the main content area changes colour too. Most obviously, the Electronics navigation is displayed vertically whereas the Automation navigation is horizontal.

What defines a Layout page is a call to the RenderBody method. In this exercise you created a layout page from _MainLayout.cshtml by placing @RenderBody() in the file, and by matching that with Layout declarations in both the _AutomationLayout.cshtml and ElectronicsLayout.cshtml files. You also added calls to RenderBody in both of those files, thus turning them into layout pages. Electronics.cshtml and Automation.cshtml each contained Layout declarations pointing to their own layout page, completing the content – layout relationship. There is no limit to the number of levels to which you can nest layout pages.

The design of the pages won’t win any awards, but this sample serves to illustrate that nesting layout pages can offer a very flexible solution to certain problems.

A small sample containing the code in full can be downloaded here

 

Date Posted: Friday, December 17, 2010 1:27 PM
Last Updated: Tuesday, November 11, 2014 8:14 AM
Posted by: Mikesdotnetting
Total Views to date: 121876

7 Comments

Friday, December 17, 2010 2:16 PM - BlueCoder

...as always simple and clear.

Tuesday, December 21, 2010 11:00 AM - Esh

I am new to Webmatrix and this article should qualify as an excellent tutorial for learning. Thanks.

Wednesday, January 19, 2011 1:28 PM - jalchr

Pretty nice .... I was wondering why don't your provide these is a sample application ... that would help us alot

Thanks

Wednesday, January 19, 2011 2:45 PM - Mike

@jalchr

I thought I had already done that, but obviously not. I have updated the article with a link to a download now.

Tuesday, April 19, 2011 6:38 AM - Huummm

Why not provide a project that can run in VS 2010. Seeing it rendered in VS can clear up things if one cant get their attempt to work correctly

Tuesday, April 19, 2011 9:29 AM - Mike

@Huummm

I'm not sure I follow what you are suggesting. The article is aimed at WebMatrix users who are unlikely to have Visual Studio, and it's easy enough to run the sample using WebMatrix without having to go and fire up the almighty beast that is VS2010. But if you think you can gain something by running the code in VS, then you can always click on the Visual Studio button in WebMatrix to do so.

Whether you run it from WebMatrix or VS, the result will be the same in each browser you test it in. It's not as if VS provides one of those awful WYSI(Not)WYG Design Views that work with Razor, and even if it did, I would never trust it.

Thursday, July 31, 2014 11:26 AM - coder

Very good article! I have tried implementing nested layout in VS2013 MVC Razor and followed all the steps mentioned in this article. Since Project doesn't have any controller, it is throwing an exception. Routeconfig.cs in the project refers to "Home" controller and "Index" actionitem. Could you please help me to run it in VS2013
Add your comment

If you have any comments to make about this article, please use this form to do so. Make sure that your comment relates specifically to the article above. More general comments can be posted through the form on the Contact page.

Please note, all comments are moderated, and some may not be published. The kind of things that will ensure your comment is deleted without ever seeing the light of day are as follows:

  • Not relevant to the article
  • Gratuitous links to your own site or product
  • Anything abusive or libellous
  • Spam
  • Anything in a language I don't understand including gibberish.

I do not pass email addresses on to spammers, so a valid one will assist me in responding to you personally if required.

Recent Comments

Allen Michaels 12/17/2014 4:37 PM
In response to Cascading DropDownLists with jQuery and ASP.NET
Fantastic thank you so much!...

Emily 12/17/2014 12:36 PM
In response to Parameterized IN clauses with ADO.NET and LINQ
Thanks, very helpful!!!! Can i use this for multiple in's ????? IN (.....) and IN(...) and IN...

sss 12/16/2014 3:06 PM
In response to Solving the Operation Must Use An Updateable Query error
good...

Gjuro 12/15/2014 10:30 PM
In response to Examining the Edit Methods and Edit View
You have one fromr (and it should be from, I suppose). :-)...

Gjuro 12/15/2014 10:27 PM
In response to Adding Search
Hi, thnx for all this C#->VB translations. Yet, the following code block is (slightly) in error it a...

Scot 12/14/2014 1:39 PM
In response to Entity Framework 6 Recipe - Alphabetical Paging In ASP.NET MVC
Thanks,Mike I found solution....

Gjuro 12/13/2014 10:52 PM
In response to Accessing Your Model's Data from a Controller
The article mentions "Creating an Entity Framework Data Model for an ASP.NET MVC Application" (at is...

Samuel 12/13/2014 8:40 AM
In response to Displaying The First n Characters Of Text
I have failed to use the extension because it throws an error that it doesn't recognise the chop be...

Ignas 12/12/2014 5:11 PM
In response to Cleaner Conditional HTML Attributes In Razor Web Pages
Any suggestions for Html Helper elements with HtmlAttributes, when you need to conditionally set it...

Gautam 12/11/2014 8:50 PM
In response to Validation In Razor Web Pages 2
Hi Mike Is this required for V3, non html helper input...