iT邦幫忙

2026 iThome 鐵人賽

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

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

Day 18|`return View()` 沒寫檔名,MVC 怎麼找到對應的 `.cshtml`?

  • 分享至 

  • xImage
  •  

上一篇已經把這條線接起來:

網址
↓
Route
↓
Controller
↓
Action

例如:

/Home/Index

常見情況下會進到:

HomeController.Index()

但接著看到:

public IActionResult Index()
{
    return View();
}

我又卡住了。

View() 裡面明明什麼都沒寫,
MVC 怎麼知道要找 Index.cshtml?

後來才知道,MVC 很常靠的是:

命名慣例

也就是 Controller 名稱、Action 名稱和 View 資料夾之間,通常有一套固定對應方式。

先看最基本的對應

假設 Controller 是:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
}

MVC 看到目前執行的是:

HomeController
↓
Index()

return View() 沒有另外指定名稱。

這時就會按照慣例去找:

Views/Home/Index.cshtml

可以拆成:

HomeController
去掉 Controller
↓
Home

Index()
↓
Index.cshtml

最後組成:

Views/Home/Index.cshtml

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

我會先記這個公式

Views
/
Controller 名稱
/
Action 名稱.cshtml

例如:

HomeController
↓
Views/Home
Index()
↓
Index.cshtml

所以:

HomeController.Index()
↓
Views/Home/Index.cshtml

再換一個例子。

public class UserController : Controller
{
    public IActionResult Edit()
    {
        return View();
    }
}

就會優先找:

Views/User/Edit.cshtml

也就是:

UserController
↓
User

Edit()
↓
Edit.cshtml

所以 return View() 的意思不是「隨便找一支 View」

不是。

當沒有指定 View 名稱時,它會根據目前 Action 的資訊去找對應畫面。

例如:

public IActionResult Detail()
{
    return View();
}

如果這個方法在:

ProductController

裡面。

MVC 會優先找:

Views/Product/Detail.cshtml

所以:

return View();

背後其實隱含了:

目前是哪個 Controller?
目前是哪個 Action?

如果 Action 和 View 不想同名呢?

可以自己指定。

例如:

public IActionResult Index()
{
    return View("HomePage");
}

這時候就不是找:

Index.cshtml

而是找:

HomePage.cshtml

HomeController 裡可能會找:

Views/Home/HomePage.cshtml

所以:

return View();

代表:

依照目前 Action 名稱找 View

而:

return View("HomePage");

代表:

我要指定 HomePage 這支 View

return View("History") 會執行 History() 嗎?

不會。

這個地方我一開始很容易混亂。

假設:

public IActionResult Index()
{
    return View("History");
}

這代表:

現在仍然執行的是 Index()

只是最後不要用 Index.cshtml,改用:

History.cshtml

也就是:

Index()
↓
return View("History")
↓
History.cshtml

它並不會再跑去執行:

public IActionResult History()
{
    ...
}

這點很重要。

那要真的跑去另一個 Action 呢?

這時就不是:

return View("History");

而可能會看到:

return RedirectToAction("History");

兩個意思完全不同。

return View("History")

目前還是在這個 Action
↓
直接使用 History.cshtml 產生畫面

RedirectToAction("History")

告訴瀏覽器重新發出請求
↓
再進到 History Action

例如:

public IActionResult Index()
{
    return RedirectToAction("History");
}

public IActionResult History()
{
    return View();
}

流程會是:

Index()
↓
RedirectToAction("History")
↓
重新請求
↓
History()
↓
return View()
↓
History.cshtml

所以看到:

View

和:

RedirectToAction

不要把它們當成同一件事。

MVC 只會找 Controller 對應的資料夾嗎?

通常還會看到另一個重要位置:

Views/Shared

例如:

Views
├── Home
│   └── Index.cshtml
│
└── Shared
    ├── _Layout.cshtml
    └── Error.cshtml

假設 HomeController 裡:

public IActionResult Error()
{
    return View();
}

MVC 可能先找:

Views/Home/Error.cshtml

如果沒有,再找:

Views/Shared/Error.cshtml

所以可以先把常見查找概念記成:

先找目前 Controller 對應資料夾

找不到
↓
再找 Views/Shared

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

不過實際企業專案也可能有:

Areas
自訂 ViewLocation
其他 Razor 設定

所以這篇先掌握最常見的慣例就好。

如果 View 放錯資料夾會怎樣?

假設 Controller 是:

public class UserController : Controller
{
    public IActionResult Edit()
    {
        return View();
    }
}

照慣例應該有:

Views/User/Edit.cshtml

但如果我不小心放成:

Views/Home/Edit.cshtml

那 MVC 不會因為專案裡「剛好有一支 Edit.cshtml」就自動找到。

因為它還會看:

目前是哪個 Controller

所以這時可能出現找不到 View 的錯誤。

找不到 View 時,錯誤訊息其實很好用

如果 MVC 找不到 View,通常錯誤訊息會告訴你:

它找過哪些路徑

例如可能看到類似:

The view 'Edit' was not found.

The following locations were searched:

/Views/User/Edit.cshtml
/Views/Shared/Edit.cshtml

這種錯誤其實很有用。

因為它直接告訴我:

MVC 現在認為 Controller 是 User

它正在找 Edit.cshtml

所以如果實際檔案放在:

Views/Home/Edit.cshtml

我就知道問題在哪了。

https://ithelp.ithome.com.tw/upload/images/20260813/201814990yWKJf91be.png

那我要怎麼從 Controller 找到真正的 View?

現在如果我看到:

public IActionResult Edit()
{
    return View();
}

我會先做這幾件事。

第一步:看 Controller 名稱

例如:

UserController

先得到:

User

第二步:看 Action 名稱

例如:

Edit

第三步:組出可能的路徑

Views/User/Edit.cshtml

第四步:確認 View() 有沒有另外指定名稱

如果是:

return View();

就用 Action 名稱找。

如果是:

return View("Detail");

就改找:

Views/User/Detail.cshtml

第五步:還是找不到,再看 Shared

Views/Shared

我的追法就會變成:

Controller 名稱
↓
Action 名稱
↓
return View() 有沒有指定 View
↓
Views/ControllerName
↓
Views/Shared

比直接在 Views 裡面亂翻快很多。

return View() 可以傳資料嗎?

可以。

例如:

public IActionResult Index()
{
    var userName = "Abbie";

    return View(userName);
}

這時:

return View(userName);

不是說 View 名稱叫做 userName

而是:

仍然按照目前 Action 找 View

同時把 userName 當資料傳進去

所以:

Index()
↓
return View(userName)
↓
Views/Home/Index.cshtml
+
userName 資料

也可以同時指定 View 名稱和資料:

return View("Detail", model);

這代表:

使用 Detail.cshtml

+

把 model 傳進去

下一篇就會正式整理:

Controller 到底怎麼把資料交給 View?

View() 常見寫法整理

先整理四個很常看到的寫法。

1. View()

return View();

代表:

使用目前 Action 名稱找 View

2. View("Detail")

return View("Detail");

代表:

使用指定名稱的 View

3. View(model)

return View(model);

代表:

使用目前 Action 對應的 View
+
傳入 model

4. View("Detail", model)

return View("Detail", model);

代表:

使用 Detail View
+
傳入 model

整理成表格:

寫法 View 怎麼找 有沒有傳資料
View() 依目前 Action 名稱 沒有
View("Detail") 指定 Detail 沒有
View(model) 依目前 Action 名稱
View("Detail", model) 指定 Detail

這跟上一篇 Route 的關係是什麼?

現在就可以把 Day 17 和 Day 18 接起來。

假設網址:

/Home/Index

第一段:

/Home/Index
↓
Route
↓
HomeController
↓
Index()

接著 Action:

public IActionResult Index()
{
    return View();
}

第二段:

HomeController
+
Index()
↓
return View()
↓
Views/Home/Index.cshtml

所以完整流程變成:

瀏覽器
↓
Route
↓
Controller
↓
Action
↓
View

這才是目前真正接起來的 MVC 流程。

_Layout.cshtml 又在哪裡進來?

前面已經學過:

Index.cshtml

可能不是完整頁面。

當 MVC 找到:

Views/Home/Index.cshtml

之後,Razor 還可能繼續套用:

_ViewStart.cshtml
↓
_Layout.cshtml

最後才產生完整 HTML。

所以整條線可以再拉長:

網址
↓
Route
↓
Controller
↓
Action
↓
return View()
↓
找到 Index.cshtml
↓
_ViewStart.cshtml
↓
_Layout.cshtml
↓
@RenderBody()
↓
產生完整 HTML
↓
瀏覽器

前面那些 View 的知識,現在終於跟 Controller 接起來了。

實際追企業專案時,我會怎麼做?

如果我只找到 Controller:

public IActionResult Detail(int id)
{
    return View();
}

但不知道畫面在哪裡。

我現在會先:

1. 確認 Controller 名稱
↓
2. 確認 Action 名稱
↓
3. 看 return View() 有沒有指定名稱
↓
4. 去 Views/ControllerName 找
↓
5. 找不到再看 Shared
↓
6. 打開 View 後再確認 Layout 和 Partial

例如:

ProductController
↓
Detail()
↓
return View()

我就先找:

Views/Product/Detail.cshtml

如果是:

return View("Info");

就改找:

Views/Product/Info.cshtml

這樣就不用看到:

return View();

還在想:

到底是哪一支啦 XD

這篇先記住什麼?

最重要的是:

return View();

並不是真的「什麼都沒指定」。

MVC 會利用目前的:

Controller 名稱
Action 名稱

按照命名慣例尋找 View。

最基本的規則可以先記成:

Controller:

HomeController

Action:

Index()

↓

View:

Views/Home/Index.cshtml

如果自己指定:

return View("Detail");

則會改找:

Detail.cshtml

另外:

return View("History");

只是:

使用 History View

不代表執行:

History Action

要重新進入另一個 Action,通常會看到:

RedirectToAction(...)

目前整條 MVC 流程已經可以先串成:

網址
↓
Route
↓
Controller
↓
Action
↓
return View()
↓
找到 .cshtml
↓
Razor 組成 HTML
↓
瀏覽器

下一篇就接著看:

Controller 已經知道要使用哪個 View 了,那查到的資料到底怎麼交給 .cshtml 顯示?


上一篇
Day 17|輸入網址之後發生什麼事?從 Route 找到 Controller 和 Action
下一篇
Day 19|Controller 怎麼把資料交給 View?ViewData、ViewBag 和 Model
系列文
學過一點 React,卻被撈進 C#:新手用 AI 硬啃 MVC 企業專案的 3 個月實錄19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言