iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
佛心分享-IT 人自學之術

學過一點 React,卻被撈進 C#:新手用 AI 硬啃 MVC 企業專案的 3 個月實錄系列 第 14

Day 14|`_Layout.cshtml` 是什麼?共用版型和 `@RenderBody()` 怎麼組成完整頁面?

  • 分享至 

  • xImage
  •  

上一篇一路從 SCSS 追到 CSS,再追到瀏覽器。

追到最後,我發現很多共用 CSS、JavaScript,甚至 Header、Sidebar、Footer,根本不在目前這支 Index.cshtml 裡。

這時候就會遇到:

_Layout.cshtml

一開始我看到它,只知道好像跟「版型」有關。

但真的要改企業專案時,比起只知道它是共用版型,更重要的是:

_Layout.cshtml 到底怎麼用?
View 怎麼套上它?
@RenderBody() 到底放了什麼?
我要怎麼從目前頁面找到它?
修改它又會影響哪些地方?

這篇就直接從實際使用方式來看。

_Layout.cshtml 可以先理解成網站的共用外框

假設一個系統有很多頁面:

首頁
最新消息
使用者管理
專案管理
設定頁

每一頁中間的內容可能不一樣。

但通常會共用:

Header
Sidebar
Footer
網站 Logo
導覽列
共用 CSS
共用 JavaScript

如果每一個 .cshtml 都重新寫一次這些內容,之後 Header 改一個按鈕,就可能要改很多頁。

所以 MVC 會把這些共用內容集中到 Layout。

最常見的位置是:

Views
└── Shared
    └── _Layout.cshtml

https://ithelp.ithome.com.tw/upload/images/20260813/20181499t5Bl5U9o0y.png

實際上怎麼使用 _Layout.cshtml

我目前會把它記成四個步驟:

1. 建立 _Layout.cshtml
2. 在 Layout 裡放 @RenderBody()
3. 指定 View 要使用這個 Layout
4. 一般 View 只寫自己這一頁的內容

先從最基本的結構開始。

第一步:建立 _Layout.cshtml

例如:

Views
└── Shared
    └── _Layout.cshtml

內容可以先很簡單:

<!DOCTYPE html>
<html lang="zh-Hant">

<head>
    <meta charset="utf-8" />

    <title>@ViewData["Title"]</title>
</head>

<body>

    <header>
        <h1>我的網站</h1>
    </header>

    <main>
        @RenderBody()
    </main>

    <footer>
        <p>共用 Footer</p>
    </footer>

</body>
</html>

這支檔案主要負責:

完整 HTML 外框
共用 Header
共用 Footer
共用 CSS
共用 JavaScript

真正每一頁不同的內容,則會放在:

@RenderBody()

這裡。

至於共用 CSS、JavaScript,也很常在 Layout 裡統一載入,只是這篇先不把完整標籤放進範例裡。

可以先理解成:

_Layout.cshtml

會負責:

共用 HTML 結構
共用 CSS
共用 JavaScript
共用 Header
共用 Sidebar
共用 Footer

第二步:在 Layout 裡放 @RenderBody()

假設 Layout 裡有:

<main>
    @RenderBody()
</main>

可以先把它理解成:

這裡先空著

等目前 View 執行時
再把那一頁自己的內容塞進來

例如 Index.cshtml

<h2>首頁</h2>

<p>這是首頁內容。</p>

最後這段內容就會被放進:

@RenderBody()

的位置。

也就是:

_Layout.cshtml
↓
Header

@RenderBody()
↓
Index.cshtml 的內容

Footer

https://ithelp.ithome.com.tw/upload/images/20260813/20181499y5AZMyhFFo.png

所以 @RenderBody() 我現在會直接把它記成:

目前這個 View 的主要內容
要被放進來的位置

第三步:指定 View 要使用哪個 Layout

最直接的方式,是在 View 裡寫:

@{
    Layout = "_Layout";
}

例如:

@{
    Layout = "_Layout";
    ViewData["Title"] = "首頁";
}

<h2>首頁</h2>

<p>這是首頁內容。</p>

這代表:

Index.cshtml
↓
使用 _Layout.cshtml

如果目前專案有:

Views/Shared/_Layout.cshtml

就可以使用這個共用版型。

但企業專案通常不會每一頁都自己寫 Layout = "_Layout"

如果有很多 View:

Index.cshtml
Create.cshtml
Edit.cshtml
Detail.cshtml
History.cshtml

每一頁都寫:

@{
    Layout = "_Layout";
}

其實很重複。

所以更常見的是:

Views
└── _ViewStart.cshtml

裡面統一設定:

@{
    Layout = "_Layout";
}

這樣底下的 View 通常就不用自己再寫。

專案結構可能長這樣:

Views
├── _ViewStart.cshtml
│
├── Shared
│   └── _Layout.cshtml
│
└── Home
    ├── Index.cshtml
    └── About.cshtml

關係就是:

_ViewStart.cshtml
↓
指定使用 _Layout.cshtml

_Layout.cshtml
↓
提供共用外框

Index.cshtml
↓
提供首頁自己的內容

下一篇會再詳細整理 _ViewStart.cshtml

https://ithelp.ithome.com.tw/upload/images/20260813/20181499eyNaGQLZCw.png

第四步:一般 View 只寫自己這一頁的內容

假設:

Views/Home/Index.cshtml

只需要寫:

@{
    ViewData["Title"] = "首頁";
}

<h1>首頁</h1>

<p>這是首頁自己的內容。</p>

不需要在每一支 View 裡都重新寫完整的:

html
head
body

因為這些共用的外框已經放在 _Layout.cshtml 裡。

所以可以先理解成:

_Layout.cshtml
提供:

html
head
body
Header
Footer
共用 CSS
共用 JavaScript

+

Index.cshtml
提供:

首頁自己的內容

MVC 再把 Index.cshtml 的內容放進:

@RenderBody()

最後到底會組成什麼?

假設 _Layout.cshtml 是:

<body>

    <header>
        共用 Header
    </header>

    <main>
        @RenderBody()
    </main>

    <footer>
        共用 Footer
    </footer>

</body>

Index.cshtml 是:

<h2>首頁</h2>

<p>歡迎來到首頁。</p>

最後產生的 HTML,可以先想成:

body

├─ Header
│  └─ 共用 Header
│
├─ main
│  ├─ 首頁
│  └─ 歡迎來到首頁
│
└─ Footer
   └─ 共用 Footer

也就是:

Layout
+
View
↓
完整 HTML

瀏覽器收到的是 _Layout.cshtml 嗎?

不是。

瀏覽器最後收到的仍然只是 HTML。

流程是:

_Layout.cshtml
+
Index.cshtml
↓
Razor 在伺服器端處理
↓
產生完整 HTML
↓
回傳瀏覽器

所以瀏覽器根本不知道:

這段原本來自 _Layout.cshtml

這段原本來自 Index.cshtml

它只看到最後組好的 HTML。

這點跟前面幾篇其實可以接起來。

瀏覽器最後真正認得的還是:

HTML
CSS
JavaScript

.cshtml 是伺服器端拿來產生 HTML 的 Razor View。

Header、Sidebar、Footer 一定直接寫在 Layout 嗎?

不一定。

如果內容很短,可以直接寫在 _Layout.cshtml

但企業專案裡這些區塊通常比較大,所以也可能拆出去:

Views
└── Shared
    ├── _Layout.cshtml
    ├── _Header.cshtml
    ├── _Sidebar.cshtml
    └── _Footer.cshtml

Layout 再把它們組起來。

概念上可以想成:

_Layout.cshtml

├─ _Header.cshtml
│
├─ _Sidebar.cshtml
│
├─ @RenderBody()
│
└─ _Footer.cshtml

所以 Layout 也可以理解成:

負責把整個頁面的大架構組起來

至於這些 _Header.cshtml_Sidebar.cshtml 怎麼放進 Layout,後面講 Partial View 時再整理。

CSS 和 JavaScript 為什麼常放在 Layout?

這就跟上一篇接起來。

假設有一支共用 CSS:

~/css/site.css

還有一支共用 JavaScript:

~/js/site.js

如果是在 _Layout.cshtml 裡統一載入,所有使用這個 Layout 的頁面通常就都會一起使用。

所以像這些:

網站基本樣式
Header 樣式
Sidebar 樣式
Bootstrap
共用 JavaScript

就很適合集中在 Layout。

這也是為什麼我有時候明明在:

Index.cshtml

裡完全找不到:

site.css

但瀏覽器畫面還是有樣式。

因為它可能根本不是在這支 View 裡載入,而是在:

_Layout.cshtml

統一處理。

所以追畫面時,不能只看目前這一支 .cshtml

如果我要改單一頁面,應該改 Layout 嗎?

不一定。

這是實際工作時很重要的一個判斷。

假設需求是:

首頁的卡片間距要調大

如果只有首頁要改,就不一定要碰:

_Layout.cshtml

因為 Layout 可能是很多頁共用的。

如果直接修改:

共用容器
共用 Header
共用 Sidebar
共用 CSS

其他頁面也可能一起被影響。

所以我現在會先問:

這個修改是全站共用?

還是只有目前這一頁?

如果需求是:

全站 Header 多一個按鈕

比較可能去找:

Layout
或 Header Partial

如果需求是:

只有首頁多一張卡片

通常應該先去找:

Index.cshtml

而不是直接改 Layout。

我怎麼知道目前這一頁到底用了哪個 Layout?

實際追專案時,我會這樣找。

先打開目前 View:

Views/Home/Index.cshtml

第一步先看上方有沒有:

@{
    Layout = "_Layout";
}

如果有,就直接知道目前指定的是哪一個 Layout。

如果沒有,再找:

_ViewStart.cshtml

看裡面是不是有:

@{
    Layout = "_Layout";
}

接著再去找:

Views/Shared/_Layout.cshtml

找到實際版型。

最後在 _Layout.cshtml 搜尋:

@RenderBody()

就可以知道:

目前 Index.cshtml 的內容
最後會被放在哪個位置

我的追法會是:

目前 View
↓
有沒有自己指定 Layout?
↓
沒有就找 _ViewStart.cshtml
↓
找到 Layout 名稱
↓
開啟 _Layout.cshtml
↓
找到 @RenderBody()
↓
對照瀏覽器畫面

這也是我現在看到一個 MVC 頁面時,很常用的追法。

修改 _Layout.cshtml 前,我會先確認什麼?

因為 Layout 可能一次影響很多頁面,所以我現在不會看到東西就直接改。

我會先確認:

1. 目前 View 使用的是不是這個 Layout?

2. 這個 Layout 有沒有被其他頁面共用?

3. 我要改的是共用區塊,還是單頁內容?

4. CSS 和 JavaScript 是全站需要,還是只有目前頁面需要?

修改後也不能只測目前這一頁。

至少還會看看:

Header 有沒有跑版
Sidebar 有沒有壞
其他頁面是否正常
CSS 是否正常載入
JavaScript 是否正常

因為:

改 Index.cshtml
可能只影響首頁

改 _Layout.cshtml
可能一次影響很多頁

這個差別在企業專案裡很重要。

一個專案只能有一個 Layout 嗎?

不是。

一個專案裡完全可能同時有:

_Layout.cshtml
一般系統頁面

_AdminLayout.cshtml
後台頁面

_LoginLayout.cshtml
登入頁面

某個 View 也可以另外指定:

@{
    Layout = "_AdminLayout";
}

所以 Layout 不是:

整個專案只能有一個版型

而是:

一群頁面可以共用同一個版型

不同類型的頁面,也可以使用不同 Layout。

@RenderBody() 可以有很多個嗎?

一般 Layout 會有一個主要的:

@RenderBody()

它負責放:

目前 View 的主要內容

但有時候除了主要內容之外,某些頁面還需要自己的:

頁面專用 JavaScript
頁面專用 CSS
額外區塊

這時候就可能會看到:

RenderSection

RenderBodyRenderSection 的用途不太一樣,後面會再一起整理。

實際使用 _Layout.cshtml 的起手式

如果今天自己建立一個最小 MVC View 結構,我會先這樣做。

Views/_ViewStart.cshtml

@{
    Layout = "_Layout";
}

Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />

    <title>@ViewData["Title"]</title>
</head>

<body>

    <header>
        <h1>我的網站</h1>
    </header>

    <main>
        @RenderBody()
    </main>

    <footer>
        <p>共用 Footer</p>
    </footer>

</body>
</html>

Views/Home/Index.cshtml

@{
    ViewData["Title"] = "首頁";
}

<h2>首頁</h2>

<p>這是首頁自己的內容。</p>

三支檔案的工作就是:

_ViewStart.cshtml
↓
決定使用哪個 Layout

_Layout.cshtml
↓
提供共用版型
並用 @RenderBody() 預留主要內容位置

Index.cshtml
↓
提供目前頁面自己的內容

這就是 _Layout.cshtml 最基本也最實際的使用方式。

這篇先記住什麼?

_Layout.cshtml 不是單純「另一支 .cshtml」。

它的主要用途是:

建立多個 View 共用的頁面外框

最常見的實際用法可以整理成:

Views/_ViewStart.cshtml
↓
指定:

Layout = "_Layout"

↓

Views/Shared/_Layout.cshtml
↓
建立共用:

Header
Sidebar
Footer
CSS
JavaScript

並放:

@RenderBody()

↓

Views/Home/Index.cshtml
↓
只寫首頁自己的內容

最後:

_Layout.cshtml
+
Index.cshtml
↓
Razor
↓
完整 HTML
↓
瀏覽器

所以之後接到畫面修改需求時,我現在會先判斷:

這是單頁內容?
→ 找目前 View

這是共用 Header、Sidebar、Footer?
→ 找 Layout 或 Partial View

不知道目前用了哪個 Layout?
→ 從 View 和 _ViewStart.cshtml 往回找

這樣 _Layout.cshtml 就不是只停在「共用版型」四個字,而是真的知道在專案裡要去哪裡找、怎麼使用,以及修改前要注意什麼。

下一篇接著整理:

_ViewStart.cshtml_ViewImports.cshtml 都放在 Views 裡,也都有底線,它們到底各自在幫 View 做什麼?


上一篇
Day 13|SCSS 到底怎麼跑到畫面上?從編譯、CSS 到瀏覽器一次追完
系列文
學過一點 React,卻被撈進 C#:新手用 AI 硬啃 MVC 企業專案的 3 個月實錄14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言