Building a maintainable UI is about more than just HTML. It's about avoiding duplication (DRY) and ensuring your 50+ pages look consistent and load fast.
The layout is your global shell. It handles the <head>, navigation, and footers. Any page-specific content is injected into the @RenderBody() method.
Sometimes a page needs a specific CSS file or a Google Maps script that other pages don't. Instead of loading it globally (slowing down the whole site), use Sections.
// In your _Layout.cshtml
<head>
<link rel="stylesheet" href="~/css/site.css" />
@RenderSection("Styles", required: false)
</head>
// In your ProductDetails.cshtml
@section Styles {
<link rel="stylesheet" href="~/css/gallery-zoom.css" />
}
A Partial View is a reusable .cshtml file that contains a small snippet of HTML. It is perfect for headers, navigation, or repetitive "Product Cards" in a list.
// _CustomerCard.cshtml
@model Toolliyo.Models.Customer
<div class="card p-3 shadow-sm">
<h4>@Model.Name</h4>
<p>Joined on @Model.JoinDate.ToShortDateString()</p>
<button class="btn btn-primary">View Profile</button>
</div>
// Usage in Index.cshtml
@foreach(var customer in Model.TopCustomers) {
<partial name="_CustomerCard" model="customer" />
}
In a 12-year expert architect's workflow, we never pass database entities directly to the view. We use a **ViewModel**. It only contains what the UI needs, preventing Over-Posting Attacks and keeping your view type-safe.
// The ViewModel
public class UserProfileViewModel {
public string DisplayName { get; set; }
public string PhotoUrl { get; set; }
public int UnreadCount { get; set; }
}
// The UI (Razor)
@model UserProfileViewModel
<div class="profile-header text-white">
<img src="@Model.PhotoUrl" alt="User Avatar" />
<h1>Welcome, @Model.DisplayName</h1>
<span class="badge">@Model.UnreadCount Messages</span>
</div>
Partial Views are light, but if a component needs its own logic (e.g. fetching the latest news from a database), a Partial View is too weak. You would have to pass the news data from every single controller. ViewComponents solve this by having their own C# class and database logic independent of the controller.
Senior architects use Async ViewComponents for any non-trivial logic. Because they run asynchronously, the browser can start rendering the rest of your layout while the component fetches data. This is how you build high-performance dashboards with 20+ dynamic widgets without making the page feel "heavy" to the user!