Views 與 Razor 語法
Razor 是什麼?
Razor 是 ASP.NET Core 的模板引擎,讓你在 HTML 中嵌入 C# 程式碼。想像它像是一台翻譯機——把混合了 C# 和 HTML 的 .cshtml 檔案翻譯成純 HTML 給瀏覽器看。
.cshtml 檔案(C# + HTML)
↓ Razor Engine 編譯
純 HTML 輸出
↓
瀏覽器顯示
基本 Razor 語法
<!-- Views/Home/Index.cshtml -->
@model List<string> <!-- 宣告此 View 的 Model 型別 -->
@{
// 程式碼區塊(C# 程式碼)
var title = "我的網站"; // 宣告變數
var count = Model.Count; // 取得 Model 的項目數
}
<h1>@title</h1> <!-- 輸出變數值 -->
<p>共有 @count 筆資料</p> <!-- 輸出變數值 -->
<p>現在時間:@DateTime.Now</p> <!-- 直接呼叫 C# -->
<!-- 條件判斷 -->
@if (count > 0)
{
<ul>
<!-- 迴圈 -->
@foreach (var item in Model)
{
<li>@item</li> <!-- 輸出每個項目 -->
}
</ul>
}
else
{
<p>目前沒有資料。</p> <!-- 沒有資料時顯示 -->
}
ViewData、ViewBag、TempData vs 強型別 Model
傳遞資料的四種方式
// Controller 中設定資料
public IActionResult Index()
{
// 方式 1: ViewData(字典,需要轉型)
ViewData["Title"] = "首頁"; // 存入 ViewData
// 方式 2: ViewBag(動態,不需轉型但無智慧提示)
ViewBag.Message = "歡迎光臨"; // 存入 ViewBag
// 方式 3: TempData(跨 Request,只能讀一次)
TempData["Alert"] = "操作成功!"; // 存入 TempData
// 方式 4: 強型別 Model(推薦!有智慧提示)
var products = GetProducts(); // 取得商品列表
return View(products); // 傳入 Model
}
<!-- View 中使用資料 -->
@model List<Product> <!-- 宣告強型別 Model -->
<h1>@ViewData["Title"]</h1> <!-- 使用 ViewData -->
<p>@ViewBag.Message</p> <!-- 使用 ViewBag -->
@if (TempData["Alert"] != null)
{
<div class="alert">@TempData["Alert"]</div> <!-- 使用 TempData -->
}
<!-- 使用強型別 Model(推薦!) -->
@foreach (var p in Model)
{
<p>@p.Name - @p.Price 元</p> <!-- 有智慧提示,不易打錯 -->
}
| 方式 | 型別安全 | 跨 Request | 推薦度 |
|---|---|---|---|
| ViewData | ❌ 需轉型 | ❌ | ⭐ |
| ViewBag | ❌ 動態 | ❌ | ⭐⭐ |
| TempData | ❌ 需轉型 | ✅ 一次 | ⭐⭐ |
| Model | ✅ 強型別 | ❌ | ⭐⭐⭐⭐⭐ |
Partial View 部分檢視
<!-- Views/Shared/_ProductCard.cshtml(部分檢視) -->
@model Product <!-- 接收單一商品 -->
<div class="card">
<h3>@Model.Name</h3> <!-- 商品名稱 -->
<p>NT$ @Model.Price</p> <!-- 商品價格 -->
<a asp-action="Details" <!-- 連結到詳細頁 -->
asp-route-id="@Model.Id">查看詳情</a>
</div>
<!-- 在主頁面中使用 Partial View -->
@model List<Product>
@foreach (var product in Model)
{
<!-- 方式 1: Tag Helper -->
<partial name="_ProductCard" model="product" />
<!-- 方式 2: HTML Helper -->
@await Html.PartialAsync("_ProductCard", product)
}
_ViewImports 與 _ViewStart
<!-- Views/_ViewImports.cshtml -->
@using DotNetLearning.Models <!-- 全域引用命名空間 -->
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <!-- 啟用 Tag Helpers -->
<!-- Views/_ViewStart.cshtml -->
@{
Layout = "_Layout"; <!-- 所有 View 預設使用 _Layout 版面 -->
}
Tag Helpers 標籤輔助
Tag Helpers 讓 HTML 標籤變得更聰明:
<!-- 表單 Tag Helpers -->
<form asp-controller="Products" <!-- 指定控制器 -->
asp-action="Create" <!-- 指定動作 -->
method="post"> <!-- HTTP 方法 -->
<div>
<label asp-for="Name"></label> <!-- 自動產生 label -->
<input asp-for="Name" /> <!-- 自動產生 name、id、驗證屬性 -->
<span asp-validation-for="Name"></span> <!-- 驗證訊息 -->
</div>
<div>
<label asp-for="Price"></label> <!-- 價格標籤 -->
<input asp-for="Price" /> <!-- 價格輸入框 -->
</div>
<button type="submit">建立</button> <!-- 送出按鈕 -->
</form>
<!-- 連結 Tag Helpers -->
<a asp-controller="Products" <!-- 連結到 Products 控制器 -->
asp-action="Details" <!-- 連結到 Details 動作 -->
asp-route-id="5">查看商品 5</a> <!-- 傳遞路由參數 id=5 -->
<!-- 產生: <a href="/Products/Details/5">查看商品 5</a> -->
🤔 我這樣寫為什麼會錯?
❌ 錯誤 1:忘記宣告 @model 導致 Model 為 null
<!-- ❌ 沒有 @model 宣告,Model 是 object 型別 -->
<h1>@Model.Name</h1> <!-- 執行時會出錯:NullReferenceException -->
<!-- ✅ 加上 @model 宣告 -->
@model Product <!-- 明確宣告 Model 型別 -->
<h1>@Model.Name</h1> <!-- 有智慧提示,編譯期就能檢查 -->
為什麼? 沒有
@model宣告,Razor 不知道 Model 的型別,無法在編譯期檢查屬性是否存在。
❌ 錯誤 2:在 Razor 中混淆 @ 符號
<!-- ❌ 想輸出電子郵件地址 -->
<p>聯絡信箱:user@example.com</p> <!-- Razor 會把 @example 當成 C# 變數 -->
<!-- ✅ 用 @@ 跳脫 -->
<p>聯絡信箱:user@@example.com</p> <!-- @@ 輸出為 @ -->
為什麼? Razor 用
@作為 C# 程式碼的起始符號,寫電子郵件時要用@@來跳脫。
❌ 錯誤 3:在 _ViewImports 忘記加 TagHelper
<!-- ❌ 沒有 @addTagHelper,Tag Helper 不會生效 -->
<a asp-controller="Home" asp-action="Index">首頁</a>
<!-- 產生: <a asp-controller="Home" asp-action="Index">首頁</a>(原封不動!) -->
<!-- ✅ 在 _ViewImports.cshtml 加上 -->
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!-- 現在 Tag Helper 才會生效 -->
<a asp-controller="Home" asp-action="Index">首頁</a>
<!-- 產生: <a href="/">首頁</a> -->
為什麼? Tag Helpers 需要透過
@addTagHelper註冊才會啟用,否則asp-*屬性只是普通的 HTML 屬性,不會被處理。