版面配置系統實現網站視覺一致性:共用 Header/Footer/Navigation、統一 CSS/JS 引用、內容區塊靈活注入。掌握 Layout、RenderBody、RenderPage、RenderSection 四大核心機制。
最簡單的重用方式:將重複片段獨立為 .cshtml 檔案,在需要處引入。
@* ~/Shared/_Header.cshtml *@
<header class="site-header">
<nav class="navbar">...</nav>
</header>
@* ~/Shared/_Footer.cshtml *@
<footer class="site-footer">
<p>© 2024 MySite. All rights reserved.</p>
</footer>
@* 內容頁 *@
<!DOCTYPE html>
<html><body>
@RenderPage("~/Shared/_Header.cshtml")
<main><h1>Welcome</h1><p>Content...</p></main>
@RenderPage("~/Shared/_Footer.cshtml")
</body></html>
優點: 簡單直觀、片段獨立維護。缺點: 每頁重複 HTML 骨架、無法強制統一結構。
@* ~/Shared/_Layout.cshtml *@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="utf-8" />
<title>@Page.Title | MySite</title>
<link href="@Href("~/Styles/site.css")" rel="stylesheet" />
@RenderSection("Head", required: false)
</head>
<body>
@RenderPage("~/Shared/_Header.cshtml")
<div class="container">
@RenderBody()
</div>
@RenderPage("~/Shared/_Footer.cshtml")
@RenderSection("Scripts", required: false)
</body>
</html>
@* 任何內容頁 *@
@{
Layout = "~/Shared/_Layout.cshtml"; // 必須為第一行非註解陳述式
Page.Title = "產品列表";
}
@section Head {
<meta name="description" content="最新產品資訊" />
<link href="@Href("~/Styles/products.css")" rel="stylesheet" />
}
<h1>產品列表</h1>
<p>內容區域自動注入到 Layout 的 @RenderBody() 位置</p>
@section Scripts {
<script src="@Href("~/Scripts/products.js")"></script>
}
| 特性 | RenderBody() | RenderSection(name) |
|---|---|---|
| 數量 | 每個版面頁**僅一個** | 可定義**多個**命名區塊 |
| 必要性 | 內容頁**必須有**主體內容 | required: true (預設) 強制提供,false 可選 |
| 用途 | 主要內容區域 | Header 補充、Sidebar、Scripts、Styles、Meta 標籤 |
| 內容頁語法 | 直接撰寫內容 | @section Name { ... } |
@* 版面頁 *@
@if (IsSectionDefined("Sidebar")) {
<aside class="sidebar">@RenderSection("Sidebar")</aside>
} else {
<aside class="sidebar"><p>預設側邊欄內容</p></aside>
}
@* 內容頁選擇性提供 *@
@section Sidebar {
<div class="widget">特別優惠內容</div>
}
IsSectionDefined("Name") 檢查內容頁是否定義區塊,實現彈性預設內容。
以 _ 開頭命名:
_Layout.cshtml_Header.cshtml_Footer.cshtml_Sidebar.cshtmlASP.NET 路由系統**攔截底線開頭檔案的直接 URL 要求**,回傳 404,保護版面結構不被外部直接存取。
@* ~/ _AppStart.cshtml (根目錄) *@
@{
// 資料庫連線字串 → 建議放 Web.config connectionStrings (可加密)
// Email 密碼 → 環境變數 / Azure Key Vault / AWS Secrets Manager
// API 金鑰 → 祕密管理服務
// 僅示範語法,實際專案請勿硬編碼
WebMail.SmtpServer = "smtp.example.com";
WebMail.UserName = "noreply@example.com";
WebMail.Password = Environment.GetEnvironmentVariable("EMAIL_PASSWORD");
WebMail.From = "noreply@example.com";
WebMail.EnableSsl = true;
}
@* ~/Admin/_Layout.cshtml (繼承根版面) *@
@{
Layout = "~/Shared/_Layout.cshtml";
}
@section Head {
<link href="@Href("~/Admin/Styles/admin.css")" rel="stylesheet" />
}
@section Scripts {
<script src="@Href("~/Admin/Scripts/admin.js")"></script>
}
<div class="admin-wrapper">
@RenderPage("~/Admin/Shared/_Sidebar.cshtml")
<main class="admin-content">@RenderBody()</main>
</div>
內容頁指定 Layout = "~/Admin/_Layout.cshtml" 即套用雙層版面。
| Web Pages | ASP.NET Core |
|---|---|
| Layout = "..." | Layout = "..." (相同語法) |
| @RenderBody() | @RenderBody() (相同) |
| @RenderSection() | @RenderSection() (相同) |
| @section Name { } | @section Name { } (相同) |
| _Layout.cshtml | Views/Shared/_Layout.cshtml / Pages/Shared/_Layout.cshtml |
| _PageStart.cshtml | _ViewStart.cshtml (指定預設 Layout) |
核心版面機制**完整保留相容**,遷移成本極低。