🎨 Views and Razor in ASP.NET MVC
The Art Gallery of Your Web Application
The Big Picture: What Are Views?
Imagine you’re running an art gallery. You have amazing paintings (your data), but you need beautiful frames and walls to display them. That’s exactly what Views do in ASP.NET MVC!
- Model = The paintings (your data)
- Controller = The curator who decides what to show
- View = The gallery walls and frames that display everything beautifully
Views are the face of your application. They turn boring data into beautiful web pages that users actually want to look at!
🪒 Razor Syntax: Your Magic Paintbrush
Razor is a special language that lets you mix C# code with HTML. Think of it as a magic paintbrush that can paint both pictures AND do math at the same time!
The @ Symbol: Your Magic Wand
The @ symbol tells Razor: “Hey! The next thing is C# code, not regular HTML!”
<h1>Hello, @Model.Name!</h1>
<p>Today is @DateTime.Now.ToShortDateString()</p>
<p>2 + 2 = @(2 + 2)</p>
Code Blocks: When You Need More Space
@{
var greeting = "Welcome!";
var count = 5;
}
<h1>@greeting</h1>
<p>You have @count messages.</p>
If-Else: Making Decisions
@if (Model.Age >= 18)
{
<p>You can vote! 🗳️</p>
}
else
{
<p>Too young to vote.</p>
}
Loops: Repeating Things
<ul>
@foreach (var fruit in Model.Fruits)
{
<li>@fruit</li>
}
</ul>
🏠 Layouts: The Master Blueprint
Think of a Layout as the blueprint of a house. Every room (page) in the house shares the same walls, roof, and foundation. You only build the unique stuff inside!
Why Layouts Are Awesome
Without layouts, you’d copy-paste the same header, footer, and navigation on EVERY page. That’s like building a new house for every room!
Creating a Layout
File: Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title - My App</title>
</head>
<body>
<header>
<nav>Home | About | Contact</nav>
</header>
<main>
@RenderBody()
</main>
<footer>© 2024 My App</footer>
</body>
</html>
Using a Layout
@{
Layout = "_Layout";
ViewBag.Title = "Home";
}
<h1>Welcome Home!</h1>
<p>This goes inside @RenderBody()</p>
Sections: Special Spots
<!-- In Layout -->
<head>
@RenderSection("Styles", required: false)
</head>
<!-- In View -->
@section Styles {
<link href="special.css" rel="stylesheet">
}
🧩 Partial Views: Reusable Puzzle Pieces
Imagine you have a LEGO block that you use in many different creations. That’s a Partial View!
Real Example: A Product Card
File: Views/Shared/_ProductCard.cshtml
@model Product
<div class="product-card">
<img src="@Model.ImageUrl" alt="@Model.Name">
<h3>@Model.Name</h3>
<p>$@Model.Price</p>
<button>Add to Cart</button>
</div>
Using Partial Views
<!-- Method 1: Html.Partial -->
@Html.Partial("_ProductCard", product)
<!-- Method 2: Tag Helper (Modern Way) -->
<partial name="_ProductCard" model="product" />
<!-- Method 3: Async (Best for Performance) -->
@await Html.PartialAsync("_ProductCard", product)
When to Use Partials
- Navigation menus
- Product cards
- Comment sections
- Sidebars
- Any repeated UI element!
💪 Strongly Typed Views: No Guessing Allowed!
Imagine ordering pizza by just saying “food please” vs “large pepperoni with extra cheese.” The second one is strongly typed!
The Problem Without Strong Typing
<!-- Dangerous! No IntelliSense, no compile-time checking -->
<h1>@ViewBag.Name</h1>
<p>@ViewBag.Prise</p> <!-- Typo! Won't catch it! -->
The Solution: @model Directive
@model Product
<!-- Safe! IntelliSense helps you, typos caught at compile -->
<h1>@Model.Name</h1>
<p>$@Model.Price</p>
Benefits
| Feature | ViewBag | Strongly Typed |
|---|---|---|
| IntelliSense | ❌ No | ✅ Yes |
| Typo Protection | ❌ No | ✅ Yes |
| Refactoring | ❌ Breaks | ✅ Works |
| Performance | Slower | Faster |
🔧 View Components: Smart Widgets
Think of View Components as smart LEGO blocks that can think for themselves! Unlike partials, they have their own brain (logic).
When to Use View Components
- Shopping cart widget (needs to count items)
- Login/logout button (needs to check auth)
- Recent posts sidebar (needs database)
Creating a View Component
Step 1: The Brain (Logic)
public class CartSummaryViewComponent : ViewComponent
{
private readonly ICartService _cart;
public CartSummaryViewComponent(ICartService cart)
{
_cart = cart;
}
public IViewComponentResult Invoke()
{
var items = _cart.GetItems();
return View(items);
}
}
Step 2: The Face (View)
File: Views/Shared/Components/CartSummary/Default.cshtml
@model List<CartItem>
<div class="cart-widget">
🛒 <span>@Model.Count items</span>
</div>
Step 3: Use It!
@await Component.InvokeAsync("CartSummary")
<!-- Or with Tag Helper -->
<vc:cart-summary></vc:cart-summary>
🏷️ Tag Helpers: HTML That Knows C#
Tag Helpers make your HTML smart! Instead of ugly code, you get beautiful, readable HTML that secretly does powerful things.
Before (Ugly)
@Html.ActionLink("Home", "Index", "Home",
null, new { @class = "nav-link" })
After (Beautiful)
<a asp-controller="Home"
asp-action="Index"
class="nav-link">Home</a>
Essential Tag Helpers
Links:
<a asp-controller="Products"
asp-action="Details"
asp-route-id="5">View Product</a>
Forms:
<form asp-controller="Account"
asp-action="Login"
method="post">
<label asp-for="Email"></label>
<input asp-for="Email" />
<span asp-validation-for="Email"></span>
<button type="submit">Login</button>
</form>
Images & Links:
<img src="~/images/logo.png"
asp-append-version="true" />
<link href="~/css/site.css"
rel="stylesheet"
asp-append-version="true" />
Common Tag Helpers
| Tag Helper | Purpose |
|---|---|
asp-controller |
Target controller |
asp-action |
Target action |
asp-route-* |
Route parameters |
asp-for |
Model binding |
asp-validation-for |
Validation |
asp-append-version |
Cache busting |
🛠️ Custom Tag Helpers: Build Your Own!
Sometimes the built-in tag helpers aren’t enough. Time to build your own!
Example: Email Link Tag Helper
[HtmlTargetElement("email")]
public class EmailTagHelper : TagHelper
{
public string Address { get; set; }
public override void Process(
TagHelperContext context,
TagHelperOutput output)
{
output.TagName = "a";
output.Attributes.SetAttribute(
"href", quot;mailto:{Address}");
output.Content.SetContent(Address);
}
}
Usage:
<email address="hello@example.com"></email>
<!-- Renders as: -->
<a href="mailto:hello@example.com">
hello@example.com
</a>
Example: Condition Tag Helper
[HtmlTargetElement(Attributes = "show-if")]
public class ShowIfTagHelper : TagHelper
{
public bool ShowIf { get; set; }
public override void Process(
TagHelperContext context,
TagHelperOutput output)
{
if (!ShowIf)
{
output.SuppressOutput();
}
}
}
Usage:
<div show-if="@User.IsAdmin">
Admin Panel Here
</div>
📬 View Data Passing: Sending Messages
There are several ways to send data from Controller to View. Think of them as different ways to send a package!
1. ViewData (Dictionary)
// Controller
ViewData["Message"] = "Hello!";
ViewData["Count"] = 42;
<!-- View -->
<p>@ViewData["Message"]</p>
<p>Count: @ViewData["Count"]</p>
2. ViewBag (Dynamic)
// Controller
ViewBag.Title = "Welcome";
ViewBag.Items = new[] { "A", "B", "C" };
<!-- View -->
<h1>@ViewBag.Title</h1>
@foreach (var item in ViewBag.Items)
{
<span>@item</span>
}
3. TempData (One-Time Messages)
// Controller (survives redirect!)
TempData["Success"] = "Item saved!";
return RedirectToAction("Index");
<!-- View -->
@if (TempData["Success"] != null)
{
<div class="alert">@TempData["Success"]</div>
}
4. Model (Strongly Typed - BEST!)
// Controller
var product = new Product {
Name = "Laptop",
Price = 999
};
return View(product);
<!-- View -->
@model Product
<h1>@Model.Name</h1>
<p>$@Model.Price</p>
Comparison Chart
graph TD A["Data Passing Methods"] --> B["ViewData"] A --> C["ViewBag"] A --> D["TempData"] A --> E["Model"] B --> B1["Dictionary<br>No IntelliSense"] C --> C1["Dynamic<br>No IntelliSense"] D --> D1["Survives Redirects<br>One-time use"] E --> E1["Strongly Typed<br>RECOMMENDED ✅"]
When to Use What?
| Method | Use When |
|---|---|
| Model | Main page data (always preferred) |
| ViewBag | Quick extras like page title |
| ViewData | When you need dictionary access |
| TempData | Success/error after redirect |
🎯 Quick Reference Flow
graph TD A["User Request"] --> B["Controller"] B --> C{Prepare Data} C --> D["Pass via Model"] C --> E["Pass via ViewBag"] D --> F["View + Razor"] E --> F F --> G{Uses} G --> H["Layout"] G --> I["Partial Views"] G --> J["View Components"] G --> K["Tag Helpers"] H --> L["Final HTML"] I --> L J --> L K --> L L --> M["User Sees Page"]
🚀 You Did It!
You now understand:
- ✅ Razor Syntax - Mixing C# with HTML
- ✅ Layouts - Master blueprints for pages
- ✅ Partial Views - Reusable UI pieces
- ✅ Strongly Typed Views - Safe, smart views
- ✅ View Components - Smart widgets with logic
- ✅ Tag Helpers - Beautiful, intelligent HTML
- ✅ Custom Tag Helpers - Build your own!
- ✅ Data Passing - ViewData, ViewBag, TempData, Model
You’re now ready to build beautiful, maintainable web pages in ASP.NET MVC! 🎉
