Menu

Nesting Layouts in MVC

4 Comments

I try to contribute to the MVC section on the asp.net forums and I sometimes see interesting questions about things I think are either obvious or that I’ve just not thought to do. This post is one such scenario: nesting layouts in MVC (master pages for WebForms people looking over the fence at MVC). Sounds easy and it pretty much is until you come to using sections.

Sections appear to catch people out as they need to be declared in the Layout specified by the content page, so if you have a sub-layout calling a master layout, how do you pass over a scripts section from the content to the master layout. This might catch a couple of people out who consider themselves proficient in MVC. The answer is as simple as nesting the sections too.

To make it nice and easy/familiar, I’ll stick with the scripts section as many people who deal with layouts will be used to that. Now imagine a site  that deals with cars. The cars are split up into categories and lets say we have a controller dedicated to the topic of sports cars.

Our graphics designer has worked hard for at least 10 minutes creating a photoshop image of a race inspired page and its layout is completely different to that of the city car topic and the family car topic.

To get every ounce of rendering speed out of our users’ browsers, we’ve decided to use a stylesheet just for this area of the site – no family car styles or city car styles.

Next up there is a script on one of our pages that needs to be rendered just for that page. Don’t ask questions, just go with it. Now we could just use the master layout page and include the sports car styles as a section in each page under the sports car area or we could be a bit fancier and use a sports car layout that includes the necessary styles and elements for the sports car pages but still calls the main layout for the site-wide common html (html declaration, the header and footer, etc.). Who wants to remember to include the styles in each new view in the sports car area. You’re not writing the html, head and body tags in each view (are you?) so why bother to repeat the style link in each view if we can use a common layout.

Now have something along the lines of a sports car page, index.cshtml for example, calling the SportsCarLayout.cshtml which is turn calls the site’s _Layout.cshtml. Everything seems to work right up until we reach the page with the custom script, the test drive page. TestDrive.cshtml plays nice and renders the script into the scripts section. Unfortunately, this now throws an error as SportsCarLayout.cshtml doesn’t have a scripts section, that scripts section is in our main layout page. If you try to add a RenderSection call (as shown below) for scripts in SportsCarLayout.cshtml it will place it in the body of the MainLayout, before our other javascript libraries. Assuming of course that you are placing your javascript at the bottom of the page, following that best practice, you are doing that aren’t you..?

@{
 Layout = "~/Views/Shared/_Layout.cshtml";
}
@section ExtraStyles
{
 @Styles.Render("~/Content/racey")
}
@RenderBody()
<!-- below code is wrong -->
@RenderSection("scripts", false)

If our test drive script relies on jQuery which is loaded via the site’s _Layout.cshtml just before the call to render the scripts section, the test drive script will fail as jQuery isn’t available as you’ve rendered it in the call to “RenderBody” of the main layout page.

Let me cut to the chase as I’m tired of writing about this imaginary car website now, you can nest sections as well as nesting layouts.

If you use the following nesting method you can call the section inside another section that will be passed on to the _Layout.cshtml page, so in your SportsCarLayout.cshtml write the following.

@section scripts
{
 @RenderSection("scripts", false)
}

This will write the script code inside the section code block which means it will then be passed along to this page’s layout. Code/script/style duplications can now be safely removed thanks to nesting layouts along with nesting sections where necessary.

4 thoughts on “Nesting Layouts in MVC”

  1. Adam O says:

    this was a big help to me, thank you

  2. Manos says:

    Very useful! thank you!

  3. Bhavik says:

    Great stuff here…

Comments are closed.