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."

ASP.NET Core MVC Mastery
Course syllabus
1. Core Framework Introduction to ASP.NET Core MVC
MODULE 1: INTRODUCTION & ENVIRONMENT SETUP Microsoft Web Stack Overview Evolution of ASP.NET Environment Setup
2. View Engine Layouts & Partial Views in Razor
MODULE 2: .NET CORE FUNDAMENTALS Core Concepts Project Structure Startup Flow Middleware Pipeline
MODULE 3: ASP.NET CORE BASICS Creating Project CLI Commands wwwroot & Static Files
MODULE 4: MVC FUNDAMENTALS MVC Architecture Dependency Injection (DI) Service Lifetimes
MODULE 5: DATA PASSING TECHNIQUES ViewData vs ViewBag TempData ViewModel Pattern
MODULE 6: ROUTING Conventional vs Attribute Routing Custom Constraints
MODULE 7: VIEWS & UI Razor View Engine Layouts & Sections View Components
MODULE 8: ACTION RESULTS ViewResult JsonResult RedirectResult
MODULE 9: HTML HELPERS Form Helpers Custom HTML Helpers
MODULE 10: TAG HELPERS Built-in Tag Helpers Custom Tag Helpers
MODULE 11: MODEL BINDING FromQuery vs FromRoute Complex Binding
MODULE 12: VALIDATION Data Annotations Remote Validation Fluent Validation
MODULE 13: STATE MANAGEMENT Cookies & Sessions TempData
MODULE 14: FILTERS & SECURITY Action Filters Authorize Filters Anti-forgery
MODULE 15: ENTITY FRAMEWORK CORE (DEEP DIVE) DbContext Migrations LINQ Relationships
MODULE 16: DESIGN PATTERNS Repository Pattern Unit of Work Clean Architecture
MODULE 17: FILE HANDLING File Upload/Download PDF/Excel Generation
MODULE 18: ADVANCED ASP.NET CORE Request Lifecycle Bundling & Minification Deployment
MODULE 19: PERFORMANCE & BEST PRACTICES Caching Strategies Async Programming Secure Coding
MODULE 20: RAZOR PAGES (BONUS) Razor Pages vs MVC
MODULE 21: REAL-WORLD PROJECTS (πŸ”₯ MUST DO) E-Commerce Web Application Employee Management System
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