Tutorials ASP.NET Core MVC Mastery

Layouts & Sections

On this page

Layouts & Sections in ASP.NET Core MVC β€” Architecting the UI Foundation

Every page on your application shares a common DNA β€” the header, navigation, footer, and meta tags. Without layouts, you'd be copy-pasting this code across hundreds of views. Layouts in ASP.NET Core MVC let you define this structure once and inject unique content into it from any view, creating a clean, maintainable UI architecture.

1. WHAT Are Layouts?

A Layout is a Razor template (.cshtml) that defines the common HTML skeleton shared by multiple views β€” the <html>, <head>, <body> tags, navigation bars, footers, and shared CSS/JS references. Individual views then inject their unique content into this skeleton via @RenderBody().

The Architecture
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         _Layout.cshtml               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  <nav> Navigation Bar </nav>   β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚                                β”‚  β”‚
β”‚  β”‚     @RenderBody()              β”‚  β”‚
β”‚  β”‚     (Your View Content Here)   β”‚  β”‚
β”‚  β”‚                                β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚  <footer> Footer </footer>     β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚  @RenderSection("Scripts")     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. The Three Pillars: RenderBody, RenderSection, _ViewStart

@RenderBody()

The mandatory placeholder where child view content is injected. Only ONE per layout. Think of it as the "main content area."

@RenderSection()

Named slots that child views can optionally fill. Perfect for page-specific CSS, JavaScript, or sidebar content. Use required: false for optional sections.

_ViewStart.cshtml

Executes before every view in its directory (and subdirectories). Used to set the default layout globally so you don't repeat Layout = "_Layout" in every view.

3. REAL-TIME PRODUCTION EXAMPLES

Example 1: Production-Ready Layout with Multiple Sections

<!-- Views/Shared/_Layout.cshtml -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="@ViewData["MetaDescription"]" />
    <title>@ViewData["Title"] β€” MyApp</title>

    <!-- Global CSS -->
    <link rel="stylesheet" href="~/css/app.min.css" />

    <!-- Page-specific CSS (optional) -->
    @RenderSection("Styles", required: false)
</head>
<body>
    <!-- Shared Navigation -->
    <partial name="_Navbar" />

    <!-- Flash Messages -->
    <partial name="_Notifications" />

    <!-- MAIN CONTENT β€” Each view's content renders here -->
    <main class="container py-4">
        @RenderBody()
    </main>

    <!-- Shared Footer -->
    <partial name="_Footer" />

    <!-- Global JS (loaded last for performance) -->
    <script src="~/js/app.min.js"></script>

    <!-- Page-specific JS (optional) -->
    @RenderSection("Scripts", required: false)
</body>
</html>

Example 2: Child View Using the Layout

<!-- Views/Products/Index.cshtml -->
@model IEnumerable<Product>
@{
    ViewData["Title"] = "All Products";
    ViewData["MetaDescription"] = "Browse our complete product catalog";
}

<h1>Product Catalog</h1>

<div class="row">
    @foreach (var product in Model)
    {
        <div class="col-md-4">
            <partial name="_ProductCard" model="product" />
        </div>
    }
</div>

@section Styles {
    <link rel="stylesheet" href="~/css/products.css" />
}

@section Scripts {
    <script src="~/js/product-filter.js"></script>
    <script>
        ProductFilter.init({ container: '.row' });
    </script>
}

Example 3: Nested Layouts (Admin vs Public)

<!-- Views/Shared/_AdminLayout.cshtml β€” Extends _Layout.cshtml -->
@{
    Layout = "_Layout";        // This layout WRAPS itself inside the main layout
    ViewData["Title"] = "Admin: " + ViewData["Title"];
}

<div class="d-flex">
    <!-- Admin Sidebar -->
    <nav class="admin-sidebar bg-dark text-white" style="width:280px; min-height:100vh;">
        <div class="p-3">
            <h5>⚑ Admin Panel</h5>
            <a href="/admin/dashboard" class="nav-link text-white">Dashboard</a>
            <a href="/admin/users" class="nav-link text-white">Users</a>
            <a href="/admin/products" class="nav-link text-white">Products</a>
            <a href="/admin/orders" class="nav-link text-white">Orders</a>
        </div>
    </nav>

    <!-- Admin Content Area -->
    <main class="flex-grow-1 p-4">
        @RenderBody()
    </main>
</div>
<!-- Views/Admin/Dashboard.cshtml β€” Uses the nested admin layout -->
@{
    Layout = "_AdminLayout";   // Uses the admin layout (which wraps inside _Layout)
    ViewData["Title"] = "Dashboard";
}

<h2>Welcome to the Admin Dashboard</h2>
<!-- This content renders inside _AdminLayout β†’ inside _Layout -->

Example 4: _ViewStart.cshtml β€” The Global Default

<!-- Views/_ViewStart.cshtml -->
@{
    Layout = "_Layout";   // ALL views in /Views/ use this layout by default
}

<!-- You can also create folder-specific _ViewStart files: -->
<!-- Views/Admin/_ViewStart.cshtml -->
@{
    Layout = "_AdminLayout";  // ALL views in /Views/Admin/ use the admin layout
}

4. Sections: Required vs Optional

// In the Layout:
@RenderSection("Scripts", required: false)    // Optional: won't crash if not defined
@RenderSection("Sidebar", required: true)     // Required: crash if view doesn't define it

// Conditional rendering with IsSectionDefined:
@if (IsSectionDefined("Sidebar"))
{
    <aside class="sidebar">
        @RenderSection("Sidebar")
    </aside>
}
else
{
    <aside class="sidebar">
        <partial name="_DefaultSidebar" />
    </aside>
}

5. Layout vs Partial View vs View Component

FeatureLayoutPartial ViewView Component
PurposePage-level HTML skeletonReusable UI fragmentSelf-contained UI + Logic
Has its own controller?❌ No❌ Noβœ… Yes (InvokeAsync)
Can access DI?Via @injectVia @injectβœ… Full DI in class
Best ForHeaders, footers, navProduct cards, formsShopping cart, recent posts
Data SourceViewData/ModelModel passed from parentOwn data from DB/service

6. Best Practices

βœ… DO
  • Use _ViewStart.cshtml for default layout assignment
  • Create folder-specific _ViewStart files for different areas (Admin, Public)
  • Use required: false for optional sections like Scripts and Styles
  • Use IsSectionDefined() to provide default content when sections aren't filled
  • Use nested layouts for Admin/Public separation
❌ DON'T
  • Don't put business logic in layouts β€” they're for structure only
  • Don't use more than one @RenderBody() in a layout
  • Don't forget to define required sections β€” it causes runtime errors
  • Don't use partial views for complex components that need their own data β€” use View Components
  • Don't inline large CSS/JS in sections β€” reference external files

7. Interview Mastery

Q: "How do you structure layouts in a large enterprise application with multiple user roles?"

Architect Answer: "I use nested layouts with folder-specific _ViewStart.cshtml files. The root _Layout.cshtml handles the outermost HTML, meta tags, and shared CSS/JS bundles. Then I create role-specific layouts β€” _AdminLayout, _CustomerLayout, _VendorLayout β€” each defining their own sidebar, navigation, and permission-aware menus. Each of these sets Layout = '_Layout' to inherit the global structure. This creates a clean hierarchy: Global β†’ Role-Specific β†’ View, keeping hundreds of views DRY while allowing each section to have its own visual identity."

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet β€” be the first to ask!

ASP.NET Core MVC Mastery
Course syllabus
1. Core Framework
MODULE 1: INTRODUCTION & ENVIRONMENT SETUP
2. View Engine
MODULE 2: .NET CORE FUNDAMENTALS
MODULE 3: ASP.NET CORE BASICS
MODULE 4: MVC FUNDAMENTALS
MODULE 5: DATA PASSING TECHNIQUES
MODULE 6: ROUTING
MODULE 7: VIEWS & UI
MODULE 8: ACTION RESULTS
MODULE 9: HTML HELPERS
MODULE 10: TAG HELPERS
MODULE 11: MODEL BINDING
MODULE 12: VALIDATION
MODULE 13: STATE MANAGEMENT
MODULE 14: FILTERS & SECURITY
MODULE 15: ENTITY FRAMEWORK CORE (DEEP DIVE)
MODULE 16: DESIGN PATTERNS
MODULE 17: FILE HANDLING
MODULE 18: ADVANCED ASP.NET CORE
MODULE 19: PERFORMANCE & BEST PRACTICES
MODULE 20: RAZOR PAGES (BONUS)
MODULE 21: REAL-WORLD PROJECTS (πŸ”₯ MUST DO)
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content onlyβ€”not admin or internal tools.

care@toolliyo.com

Need callback? Share your details