將檢視新增到 MVC 應用程式

Rick Anderson

注意

本教學課程的更新版本可在此取得,它使用最新版的Visual Studio。 新的教學課程使用 ASP.NET Core MVC,相比於本教學課程提供了許多改良。

本教學課程可讓您了解 ASP.NET Core MVC 與控制器和檢視。 Razor 頁面是 ASP.NET Core 中的新替代方案,它是以頁面為基礎的程式設計模型,可讓 Web UI 的建立更容易且更有效率。 我們建議您在嘗試 MVC 版本之前,先試試 Razor Pages 教學。 Razor 頁面教學:

  • 比較容易理解。
  • 涵蓋更多功能。
  • 是開發新應用程式的建議方法。

在本節中,您將修改 HelloWorldController 類別以使用檢視範本檔案,從而清晰地封裝生成客戶端 HTML 回應的過程。

您會使用 Razor 檢視引擎建立範本檔案。 以 Razor 為基礎的檢視範本具有 .cshtml 副檔名,且提供一套細緻的方 法,使用 C# 建立 HTML 輸出。 Razor 可將撰寫檢視範本時所需的字元數和按鍵次數降到最低,並啟用快速流暢的編碼工作流程。

目前,Index 方法會傳回字串,內容是控制器類別中硬編碼的訊息。 將Index方法變更為呼叫控制器的View方法,如以下程式碼所示:

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

上面的 Index 方法使用視圖模板來對瀏覽器產生 HTML 回應。 上述的 Index 方法這類控制器方法(亦稱為 動作方法)通常會傳回 ActionResult(或衍生自 ActionResult 的類別),而不是基本型別,如字串。

以滑鼠右鍵按一下 Views\HelloWorld 資料夾,然後點選 新增,接著點選 MVC 5 檢視頁面,包含版面配置 (Razor)

Screenshot that shows the Solution Explorer window. The Hello World right click menu and Add submenu are open and M V C 5 View Page with Layout Razor is selected.螢幕擷取畫面顯示「方案總管」視窗,「Hello World」右鍵選單和「新增」子選單已開啟,且 [MVC 5 檢視頁面與版面配置 (Razor)] 已被選取。

[指定項目名稱] 對話方塊中輸入「Index」,然後按一下 [確定]

螢幕擷取畫面顯示「為項目指定名稱」對話方塊。「項目名稱」欄位中是「Index」。

[選取版面配置頁面] 對話方塊中,接受預設的 _Layout.cshtml,然後按一下 [確定]

螢幕擷取畫面顯示「選取版面配置頁面」。

在上述對話方塊中,左窗格的 Views\Shared 資料夾已選取。 如果您在其他資料夾有自訂版面配置檔案,也可以選取。 稍後在本教學課程中,我們會討論版面配置檔案。

MvcMovie\Views\HelloWorld\Index.cshtml 檔案已建立。

螢幕擷取畫面顯示「方案總管」視窗。「Views」資料夾和「Hello World」子資料夾已開啟。

新增下列反白顯示的標記。

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

以滑鼠右鍵按一下 Index.cshtml 檔案,然後選取 [在瀏覽器中檢視]

PI

您也可以滑鼠右鍵按一下 Index.cshtml 檔案,選取 在 Page Inspector 中檢視。 如需詳細資訊,請參閱 Page Inspector 教程

或者,執行應用程式並前往 HelloWorld 控制器 (http://localhost:xxxx/HelloWorld)。 你的控制器中的Index方法不會執行太多作業;它僅執行陳述式return View(),這指定該方法應使用檢視範本檔案來渲染對瀏覽器的回應。 因為您沒有明確指定要使用的檢視範本檔案名稱,ASP.NET MVC 預設為使用 \Views\HelloWorld 資料夾中的 Index.cshtml 檢視檔案。 下圖顯示了檢視中被硬編碼的字串「Hello from our View Template!」。

螢幕擷取畫面顯示「Index」頁面和字樣「Hello from our View Template」。

看起來很不錯。 不過,請注意瀏覽器的標題列顯示「索引 - 我的 ASP.NET 應用程式」,而頁面頂端的主要連結顯示「應用程式名稱」。視您設定的瀏覽器視窗大小而定,您可能需要按一下右上方的三橫條圖示,才能查看 [首頁][關於][聯絡人][註冊][登入] 連結。

改變視圖和版面頁面

首先,您要變更頁面頂端的「應用程式名稱」連結。 該文字在每個頁面都會顯示。 即使它出現在應用程式的每個頁面,實際上僅僅實作在專案的一個位置。 前往方案總管中的/Views/Shared資料夾,然後開啟_Layout.cshtml檔案。 此檔案稱為版面配置頁面,位於所有其他頁面都會使用的共用資料夾中。

_LayoutCshtml_LayoutCshtml

版面配置範本可讓您在某個位置指定網站的 HTML 容器配置,然後將它套用到網站中的多個頁面。 找到 @RenderBody() 這行。 RenderBody 是一個預留位置,用於顯示您所建立的所有檢視特定頁面,這些頁面將被包裹在版面配置頁面中。 例如,如果您選取 About 連結,Views\Home\About.cshtml 檢視就會在 RenderBody 方法中轉譯。

變更標題元素的內容。 將版面配置範本中的 ActionLink 從「應用程式名稱」變更為「MVC 電影」,並將控制器從 Home 變更為 Movies。 完整的版面配置檔案如下所示:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Movie App</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("MVC Movie", "Index", "Movies", null, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

執行應用程式,並注意它現在顯示「MVC 電影」。 按一下 [關於] 連結,您也會看到該頁面顯示「MVC Movie」。 我們可以在版面配置範本中只變更一次,就讓網站上的所有頁面都反映新的標題。

螢幕擷取畫面顯示「MVC Movie」的關於頁面。

我們第一次建立 Views\HelloWorld\Index.cshtml 檔案時,它包含下列程式碼:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

上述 Razor 程式碼會明確設定版面配置頁面。 檢查 Views\_ViewStart.cshtml 檔案,其中包含完全相同的 Razor 標記。 Views\_ViewStart.cshtml 檔案定義了所有視圖所使用的通用版面配置,因此您可以註解或移除 Views\HelloWorld\Index.cshtml 檔案中的該程式碼。

@*@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}*@

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

您可以使用 Layout 屬性來設定不同的版面配置檢視,或將其設定為 null,以避免使用任何版面配置檔案。

接下來,我們要變更 Index 檢視的標題。

開啟 MvcMovie\Views\HelloWorld\Index.cshtml。 有兩個位置可以進行變更:首先是顯示在瀏覽器標題的文字,然後是次級標題(<h2>元素)。 您會使這些變更略有不同,因此可看出哪一段程式碼變更了應用程式的哪個部分。

@{
    ViewBag.Title = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

為了指出要顯示的 HTML 標題,上述程式碼會設定 物件的 屬性 (位於 檢視範本中)。 請注意,版面配置範本(Views\Shared\_Layout.cshtml)在我們先前修改的 HTML <head> 區段中,將此值用於 <title> 元素之中。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Movie App</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>

使用這種 ViewBag 方法,您可以輕鬆地在視圖範本和版面配置文件之間傳遞其他參數。

執行應用程式。 請注意,瀏覽器標題、主要標題和次要標題已變更 (如果瀏覽器沒有顯示變更,您可能檢視的是快取內容。在瀏覽器中按 Ctrl+F5 可強制載入伺服器的回應。) 瀏覽器標題是使用我們在 Index.cshtml 檢視範本中設定的 ViewBag.Title 及在版面配置檔案中額外加入的 "- Movie App" 所建立。

此外也請注意,Index.cshtml 檢視範本的內容已與 _Layout.cshtml 檢視範本和傳送至瀏覽器的單一 HTML 回應合併。 版面配置範本可讓您輕鬆進行會套用到應用程式之所有頁面的變更。

顯示「M V C Movie 我的電影清單」頁面的螢幕擷取畫面。

不過,我們的一小段「資料」(在本例中為「Hello from our View Template!」訊息) 採用硬編碼。 MVC 應用程式具有 "V" (檢視),並已取得 "C" (控制器),但還沒有 "M" (模型)。 我們很快會逐步解說如何建立資料庫,並從中擷取模型資料。

將資料從控制器傳遞至檢視

不過,在我們前進到資料庫並討論模型之前,先討論如何將資訊從控制器傳遞至檢視。 回應傳入的 URL 要求時系統會叫用控制器類別。 控制器類別會在您撰寫程式碼時用於處理傳入瀏覽器要求、從資料庫擷取資料,最後決定要向瀏覽器傳回何種回應類型。 您接著可以從控制器使用檢視範本來產生並格式化瀏覽器的 HTML 回應。

控制器負責提供檢視範本在向瀏覽器回應時所需的任何資料或物件,確保它能順利呈現回應。 最佳做法:檢視範本絕不應執行商務邏輯或直接與資料庫互動。 相反,檢視範本應該只使用控制器提供的資料。 維持這種「分離考量」,有助於保持程式碼的整潔與可測試,也更容易維護。

目前,Welcome 類別中的 HelloWorldController 方法會接受 namenumTimes 參數,然後將這些值直接輸出到瀏覽器。 與其讓控制器以字串方式轉譯此回應,不如將控制器改為使用檢視範本。 檢視範本會產生動態回應,這表示您需要將適當數量的資料從控制器傳遞至檢視,以便產生回應。 讓控制器將檢視範本需要的動態資料(參數)放在一個檢視範本可存取的ViewBag物件中,即可完成這項操作。

返回 HelloWorldController.cs 檔案並變更 Welcome 方法,將 MessageNumTimes 值新增至 ViewBag 物件。 ViewBag 是一個動態物件,這意味著您可以將任何想要的內容放入其中。ViewBag 物件在您放入內容之前不具有定義的屬性。 ASP.NET MVC 模型繫結系統會自動將網址列的查詢字串中具名的參數 (namenumTimes) 對應至方法中的參數。 完整的 HelloWorldController.cs 檔案如下所示:

using System.Web;
using System.Web.Mvc;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Welcome(string name, int numTimes = 1)
        {
            ViewBag.Message = "Hello " + name;
            ViewBag.NumTimes = numTimes;

            return View();
        }
    }
}

現在,ViewBag 物件包含會自動傳遞至檢視的資料。 接下來,您需要一個歡迎視圖範本! 在 [建置] 功能表中,選取 [建置解決方案] (或按 Ctrl+Shift+B),確認專案已編譯。 以滑鼠右鍵按一下 Views\HelloWorld 資料夾,然後點選 新增,接著點選 MVC 5 檢視頁面,包含版面配置 (Razor)

螢幕擷取畫面顯示「方案總管」視窗。右鍵選單「Hello World」和「新增」子選單已開啟。「MVC 5 檢視頁面,附有版面配置 Razor」已選取。

[指定項目名稱] 對話方塊中輸入「Welcome」,然後按一下 [確定]

[選取版面配置頁面] 對話方塊中,接受預設的 _Layout.cshtml,然後按一下 [確定]

螢幕擷取畫面顯示「選取版面配置頁面」。標示為「共用」的子資料夾已開啟,且「Layout.cshtml」已選取。

MvcMovie\Views\HelloWorld\Welcome.cshtml 檔案已建立。

取代 Welcome.cshtml 檔案中的標記。 您會建立一個迴圈,讓它根據使用者所指定的次數,重複顯示「Hello」。 完整的 Welcome.cshtml 檔案如下。

@{
    ViewBag.Title = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < ViewBag.NumTimes; i++)
    {
        <li>@ViewBag.Message</li>
    }
</ul>

執行應用程式並前往以下 URL:

http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4

現在資料會從 URL 取得,並使用模型繫結器傳遞至控制器。 控制器會將資料封裝成 ViewBag 物件,並將該物件傳遞至檢視。 接著,檢視會以 HTML 格式將資料呈現給使用者。

Screenshot that shows the M V C Movie Welcome page.螢幕擷取畫面所示為「MVC Movie Welcome」頁面。

在上述範例中,我們使用 ViewBag 物件,來將資料從控制器傳遞至檢視。 稍後在教學課程中,我們將使用檢視模型將控制器中的資料傳遞至檢視。 用檢視模型方法傳遞資料通常比檢視包方法更常用。 如需更多資訊,請參閱部落格文章《動態視圖對比強類型視圖》。

這是一種代表模型的 "M",但不是資料庫類型。 讓我們運用所學的內容,建立電影的資料庫。

上一個 下一個