ASP.NET MVC · Controllers & Views

Layout Pages

Every page of a site shares a header, a menu and a footer. A layout page holds that shell once, so each view only contains what is different.

Intermediate 6 min Lesson 10 of 37Covers ASP.NET MVC 5.2 on .NET Framework 4.8.
Before you start:Razor Syntax
0/37 in ASP.NET MVC
On this page · 6 min · Intermediate

Learning objectives#

  • Build a layout with RenderBody
  • Define optional and required sections
  • Set the default layout in _ViewStart
  • Pass a page title from views to the layout

Explanation#

A layout is a view (by convention Views/Shared/_Layout.cshtml) with the full HTML page. It calls @RenderBody() exactly once, where the current view’s output goes.

Views/_ViewStart.cshtml runs before every view and sets Layout = "~/Views/Shared/_Layout.cshtml", so views use it automatically. A view can set a different Layout or Layout = null.

Sections let a view put content in other places of the layout: the view writes @section scripts { ... } and the layout calls @RenderSection("scripts", required: false). If a section is required and missing, rendering fails.

The view runs before the layout, so values set in the view (ViewBag.Title) are available in the layout’s <title>.

IsSectionDefined("sidebar") lets the layout show default content when a view does not provide a section.

Syntax#

Razor / Markup Illustrative
@* _Layout.cshtml *@
<title>@ViewBag.Title</title>
<main>@RenderBody()</main>
@RenderSection("scripts", required: false)


@* A view *@
@{ ViewBag.Title = "Cart"; }
<h1>Your cart</h1>
@section scripts { <script src="~/Scripts/cart.js"></script> }

Code example: A layout with a title, a body and two sections#

C#_Layout.cshtml Illustrative
// Controllers/PagesController.cs
using System.Web.Mvc;


namespace ShopSite.Controllers
{
    public class PagesController : Controller
    {
        public ActionResult Cart() => View();
        public ActionResult Terms() => View();
    }
}


@* Views/_ViewStart.cshtml *@
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}


@* Views/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title | Shop</title>
</head>
<body>
    <header><a href="/">Shop</a></header>
    <aside>
        @if (IsSectionDefined("sidebar"))
        {
            @RenderSection("sidebar")
        }
        else
        {
            <p>Free delivery over 500 rupees</p>
        }
    </aside>
    <main>
        @RenderBody()
    </main>
    <footer>&copy; 2026 Shop</footer>
    @RenderSection("scripts", required: false)
</body>
</html>


@* Views/Pages/Cart.cshtml *@
@{ ViewBag.Title = "Your cart"; }
<h1>Your cart</h1>
<p>2 items</p>
@section sidebar {
    <p>Have a coupon? Apply it at checkout.</p>
}
@section scripts {
    <script src="/Scripts/cart.js"></script>
}


@* Views/Pages/Terms.cshtml *@
@{ ViewBag.Title = "Terms"; }
<h1>Terms of sale</h1>
Expected output
GET /Pages/Cart
200 OK
<!DOCTYPE html>
<html>
<head>
    <title>Your cart | Shop</title>
</head>
<body>
    <header><a href="/">Shop</a></header>
    <aside>
    <p>Have a coupon? Apply it at checkout.</p>
    </aside>
    <main>
<h1>Your cart</h1>
<p>2 items</p>
    </main>
    <footer>&copy; 2026 Shop</footer>
    <script src="/Scripts/cart.js"></script>
</body>
</html>

GET /Pages/Terms
200 OK
<!DOCTYPE html>
<html>
<head>
    <title>Terms | Shop</title>
</head>
<body>
    <header><a href="/">Shop</a></header>
    <aside>
            <p>Free delivery over 500 rupees</p>
    </aside>
    <main>
<h1>Terms of sale</h1>
    </main>
    <footer>&copy; 2026 Shop</footer>
</body>
</html>

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. _ViewStart sets the layout for every view in the Views folder.
  2. Cart.cshtml runs first: it sets ViewBag.Title, produces its body HTML and defines two sections.
  3. The layout then runs. The title uses the value set by the view, RenderBody inserts the body, and the sections appear where RenderSection is called.
  4. Terms defines no sections, so the layout shows the default sidebar text and the optional scripts section renders nothing.

Real-world use case#

A company rebrands its intranet. Because every one of its 140 pages uses the same _Layout.cshtml, the new header, colours and footer go live by changing one file.

Common mistakes#

Calling RenderBody twice or not at all

A layout must call RenderBody exactly once, otherwise MVC throws “The RenderBody method has not been called”.

Required section missing

@RenderSection("scripts") without required: false makes every view without that section fail. Make optional sections optional.

Setting ViewBag.Title in the layout

The layout runs after the view, so a title set in the layout overwrites the view’s title. Set it in the view.

Best practices#

  • One main layout plus specialised layouts (admin, print) that can nest
  • Put scripts in a scripts section at the end of the body
  • Use IsSectionDefined for sensible defaults
  • Keep layouts free of business logic; use child actions or partials for menus

Remember this#

Layout = shell; RenderBody = this page.

_ViewStart sets the default layout.

View runs first, layout second.

Practice exercise#

Your task: Create a _PrintLayout.cshtml with no header or footer and make an Invoice view use it by setting Layout in the view.

Need a hint?
In the view: @{ Layout = "~/Views/Shared/_PrintLayout.cshtml"; }
Show solution
C# Illustrative
// Controllers/PrintController.cs
using System.Web.Mvc;


namespace ShopSite.Controllers
{
    public class PrintController : Controller
    {
        public ActionResult Invoice() => View();
    }
}


@* Views/Shared/_PrintLayout.cshtml *@
<!DOCTYPE html>
<html>
<head><title>Print</title></head>
<body class="print">
@RenderBody()
</body>
</html>


@* Views/Print/Invoice.cshtml *@
@{ Layout = "~/Views/Shared/_PrintLayout.cshtml"; }
<h1>Invoice #1001</h1>
Expected output
GET /Print/Invoice
200 OK
<!DOCTYPE html>
<html>
<head><title>Print</title></head>
<body class="print">
<h1>Invoice #1001</h1>
</body>
</html>

Mini quiz#

Layout Pages quizMultiple choice Question 1 of 3

Which call inserts the current view into a layout?

Score so far: 0/0

Want more? Practise all ASP.NET MVC MCQs · ASP.NET MVC interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.