Advanced Layouts in ASP.NET Core MVC
In ASP.NET Core MVC, effective layout management is crucial for creating consistent and maintainable user interfaces across your application. This tutorial explores advanced techniques for structuring and utilizing layouts.
Understanding Layouts
Layouts, often implemented using Razor layout pages (.cshtml files), define the common structure of your application's pages. They act as a master template, embedding content from individual views into a predefined structure.
The _Layout.cshtml File
By default, ASP.NET Core MVC applications use a file named _Layout.cshtml located in the Views/Shared folder. This file typically contains:
- The
<!DOCTYPE html>declaration and<html>,<head>, and<body>elements. - Links to CSS and JavaScript files.
- Common UI elements like headers, footers, and navigation bars.
- The
@RenderBody()helper, which is a placeholder where the content of the current view will be rendered.
Defining a Layout
Here's a basic example of a _Layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MyApp</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MyApp</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2023 - MyApp - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
Overriding Layouts
Not all pages need to use the default layout. You can specify a different layout for a view or disable it entirely.
Specifying a Layout in a View
Within a Razor view (e.g., Views/Home/About.cshtml), you can set the Layout property in the page directive:
@{
Layout = "~/Views/Shared/_MyCustomLayout.cshtml";
}
<h1>About Us</h1>
<p>Information about our company.</p>
Disabling the Layout
To render a view without any layout (e.g., for a JSON response or a full-page component), set Layout to null:
@{
Layout = null;
}
<h1>Welcome (No Layout)</h1>
Layout Sections
Layouts can define named sections that individual views can populate. This is useful for injecting content like specific JavaScript files or CSS styles into particular areas of the layout.
Defining a Section in the Layout
In _Layout.cshtml, you can define sections using @section:
<head>
<!-- ... other head elements ... -->
@RenderSection("Styles", required: false)
</head>
<body>
<!-- ... body content ... -->
@RenderSection("Scripts", required: false)
</body>
The required: false parameter means that views are not obligated to provide content for these sections.
Populating a Section in a View
In a view, you can populate these sections:
@section Styles {
<link rel="stylesheet" href="~/css/specific-page.css" />
}
<h1>Contact Us</h1>
<p>Get in touch!</p>
@section Scripts {
<script src="~/js/contact.js"></script>
}
Advanced Layout Strategies
Partial Views for Reusable Components
Break down complex layout elements (like navigation bars, footers, or sidebars) into partial views. These can be rendered within your main layout using:
<!-- In _Layout.cshtml -->
<header>
@await Html.PartialAsync("_NavigationBar.cshtml")
</header>
Dynamic Layouts
You can dynamically determine which layout to use based on controller, action, or even user roles. This is often achieved in the controller's action method:
public class HomeController : Controller
{
public IActionResult Index()
{
// Example: Use a different layout for admin users
if (User.IsInRole("Admin"))
{
ViewBag.Layout = "_AdminLayout"; // Assuming _AdminLayout.cshtml exists
}
else
{
ViewBag.Layout = "_Layout";
}
return View();
}
}
Then, in your view:
@{
Layout = ViewBag.Layout + ".cshtml";
}
<h1>Dashboard</h1>
Layouts with Different Content Placeholders
For applications with distinctly different page structures, consider creating multiple layout files and assigning them as needed.