將視圖添加到 ASP.NET Core MVC 應(yīng)用

2019-04-17 08:57 更新

在本部分中,將修改 HelloWorldController 類,進(jìn)而使用 Razor 視圖文件來順利封裝為客戶端生成 HTML 響應(yīng)的過程。

使用 Razor 創(chuàng)建視圖模板文件。 基于 Razor 的模板具有“.cshtml”文件擴(kuò)展名。 它們提供了一種巧妙的方法來使用 C# 創(chuàng)建 HTML 輸出。

當(dāng)前,Index 方法返回帶有在控制器類中硬編碼的消息的字符串。 在 HelloWorldController 類中,將 Index 方法替換為以下代碼:

C#

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

上面的代碼調(diào)用控制器的 View 方法。 它使用視圖模板來生成 HTML 響應(yīng)。 控制器方法(亦稱為“操作方法”,如上面的 Index 方法)通常返回 IActionResult(或派生自 ActionResult 的類),而不是 string 等類型。

添加視圖

  • 右鍵單擊“視圖”文件夾,然后單擊“添加”>“新文件夾”,并將文件夾命名為“HelloWorld”。

  • 右鍵單擊“Views/HelloWorld”文件夾,然后單擊“添加”>“新項(xiàng)”。

  • 在“添加新項(xiàng) - MvcMovie”對話框中

    • 在右上角的搜索框中,輸入“視圖”

    • 選擇“Razor 視圖”

    • 保持“名稱”框的值:Index.cshtml。

    • 選擇“添加”

“添加新項(xiàng)”對話框

使用以下內(nèi)容替換 Razor 視圖文件 Views/HelloWorld/Index.cshtml 的內(nèi)容:

HTML

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

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

導(dǎo)航到 https://localhost:xxxx/HelloWorld。 HelloWorldController 中的 Index 方法作用不大;它運(yùn)行 return View(); 語句,指定此方法應(yīng)使用視圖模板文件來呈現(xiàn)對瀏覽器的響應(yīng)。 因?yàn)闆]有顯式指定視圖模板文件的名稱,所以 MVC 默認(rèn)使用 /Views/HelloWorld 文件夾中的 Index.cshtml 視圖文件。 下面圖片顯示了視圖中硬編碼的 字符串“Hello from our View Template!”

瀏覽器窗口

更改視圖和布局頁面

選擇菜單鏈接(“MvcMovie”、“首頁”和“隱私”)。 每頁顯示相同的菜單布局。 菜單布局是在 Views/Shared/_Layout.cshtml 文件中實(shí)現(xiàn)的。 打開 Views/Shared/_Layout.cshtml 文件。

布局模板使你能夠在一個位置指定網(wǎng)站的 HTML 容器布局,然后將它應(yīng)用到網(wǎng)站中的多個頁面。 查找 @RenderBody() 行。 RenderBody 是顯示創(chuàng)建的所有特定于視圖的頁面的占位符,已包裝在布局頁面中。 例如,如果選擇“隱私”鏈接,Views/Home/Privacy.cshtml 視圖將在 RenderBody 方法中呈現(xiàn)。

更改布局文件中的標(biāo)題、頁腳和菜單鏈接

  • 在標(biāo)題和頁腳元素中,將 MvcMovie 更改為 Movie App。
  • 將定位點(diǎn)元素 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a>更改為 <a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>。

下列標(biāo)記顯示了突出顯示的更改:

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet"  rel="external nofollow" target="_blank" 
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
              crossorigin="anonymous"
              integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
    </environment>
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <partial name="_CookieConsentPartial" />
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" rel="external nofollow" 
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
        </script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js" rel="external nofollow" 
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
        </script>
    </environment>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

在前面的標(biāo)記中,省略了 asp-area 定位點(diǎn)標(biāo)記幫助程序?qū)傩?/a>,因?yàn)榇藨?yīng)用未使用區(qū)域。

說明:Movies 控制器尚未實(shí)現(xiàn)。 此時,Movie App 鏈接不起作用。

保存更改并選擇“隱私”鏈接。 請注意瀏覽器選項(xiàng)卡上的標(biāo)題現(xiàn)在顯示的是“隱私策略 - 電影應(yīng)用”,而不是“隱私策略 - Mvc 電影”:

“隱私”選項(xiàng)卡

選擇“主頁”鏈接,請注意,標(biāo)題和定位文本還會顯示“電影應(yīng)用”。 我們能夠在布局模板中進(jìn)行一次更改,讓網(wǎng)站上的所有頁面都反映新的鏈接文本和新標(biāo)題。

檢查 Views/_ViewStart.cshtml 文件:

HTML

@{
    Layout = "_Layout";
}

Views/_ViewStart.cshtml 文件將 Views/Shared/_Layout.cshtml 文件引入到每個視圖中。 可以使用 Layout 屬性設(shè)置不同的布局視圖,或?qū)⑺O(shè)置為 null,這樣將不會使用任何布局文件。

更改 Views/HelloWorld/Index.cshtml 視圖文件的 <h2> 元素:

HTML

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

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

稍稍對標(biāo)題和 <h2> 元素進(jìn)行一些更改,這樣可以看出哪一段代碼更改了顯示。

上述代碼中的 ViewData["Title"] = "Movie List"; 將 ViewData 字典的 Title 屬性設(shè)置為“Movie List”。 Title 屬性在布局頁面中的 <title> HTML 元素中使用:

HTML

<title>@ViewData["Title"] - Movie App</title>

保存更改并導(dǎo)航到 https://localhost:xxxx/HelloWorld。 請注意,瀏覽器標(biāo)題、主標(biāo)題和輔助標(biāo)題已更改。 (如果沒有在瀏覽器中看到更改,則可能正在查看緩存的內(nèi)容。 在瀏覽器中按 Ctrl + F5 強(qiáng)制加載來自服務(wù)器的響應(yīng)。)瀏覽器標(biāo)題是使用我們在 Index.cshtml 視圖模板中設(shè)置的 ViewData["Title"] 以及在布局文件中添加的額外“ - Movie App”創(chuàng)建的。

還要注意,Index.cshtml 視圖模板中的內(nèi)容是如何與 Views/Shared/_Layout.cshtml 視圖模板合并的,并且注意單個 HTML 響應(yīng)被發(fā)送到了瀏覽器。 憑借布局模板可以很容易地對應(yīng)用程序中所有頁面進(jìn)行更改。 若要了解更多信息,請參閱布局。

電影列表視圖

但我們這一點(diǎn)點(diǎn)“數(shù)據(jù)”(在此示例中為“Hello from our View Template!” 消息)是硬編碼的。 MVC 應(yīng)用程序有一個“V”(視圖),而你已有一個“C”(控制器),但還沒有“M”(模型)。

將數(shù)據(jù)從控制器傳遞給視圖

控制器操作會被調(diào)用以響應(yīng)傳入的 URL 請求。 控制器類是編寫處理傳入瀏覽器請求的代碼的地方??刂破鲝臄?shù)據(jù)源檢索數(shù)據(jù),并決定將哪些類型的響應(yīng)發(fā)送回瀏覽器。 可以從控制器使用視圖模板來生成并格式化對瀏覽器的 HTML 響應(yīng)。

控制器負(fù)責(zé)提供所需的數(shù)據(jù),使視圖模板能夠呈現(xiàn)響應(yīng)。 最佳做法:視圖模板不應(yīng)該直接執(zhí)行業(yè)務(wù)邏輯或與數(shù)據(jù)庫進(jìn)行交互。 相反,視圖模板應(yīng)僅使用由控制器提供給它的數(shù)據(jù)。 保持此“分離關(guān)注點(diǎn)”有助于保持代碼干凈以及可測試性和可維護(hù)性。

目前,HelloWorldController 類中的 Welcome 方法采用 name 和 ID 參數(shù),然后將值直接輸出到瀏覽器。 應(yīng)將控制器更改為使用視圖模板,而不是使控制器將此響應(yīng)呈現(xiàn)為字符串。 視圖模板會生成動態(tài)響應(yīng),這意味著必須將適當(dāng)?shù)臄?shù)據(jù)位從控制器傳遞給視圖以生成響應(yīng)。 為此,可以讓控制器將視圖模板所需的動態(tài)數(shù)據(jù)(參數(shù))放置在視圖模板稍后可以訪問的 ViewData 字典中。

在 HelloWorldController.cs 中,更改 Welcome 方法以將 Message 和 NumTimes 值添加到 ViewData字典。 ViewData 字典是一個動態(tài)對象,這意味著可以使用任何類型;只有將內(nèi)容放在其中后 ViewData 對象才具有定義的屬性。 MVC 模型綁定系統(tǒng)自動將命名參數(shù)(name 和 numTimes)從地址欄中的查詢字符串映射到方法中的參數(shù)。 完整的 HelloWorldController.cs 文件如下所示:

C#

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

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

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

ViewData 字典對象包含將傳遞給視圖的數(shù)據(jù)。

創(chuàng)建一個名為 Views/HelloWorld/Welcome.cshtml 的 Welcome 視圖模板。

在 Welcome.cshtml 視圖模板中創(chuàng)建一個循環(huán),顯示“Hello” NumTimes。 使用以下內(nèi)容替換 Views/HelloWorld/Welcome.cshtml 的內(nèi)容:

HTML

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

保存更改并瀏覽到以下 URL:

https://localhost:xxxx/HelloWorld/Welcome?name=Rick&numtimes=4

數(shù)據(jù)取自 URL,并傳遞給使用 MVC 模型綁定器的控制器。 控制器將數(shù)據(jù)打包到 ViewData 字典中,并將該對象傳遞給視圖。 然后,視圖將數(shù)據(jù)作為 HTML 呈現(xiàn)給瀏覽器。

“隱私”視圖,顯示了 Welcome 標(biāo)簽以及四個“Hello Rick”短語

在上面的示例中,我們使用 ViewData 字典將數(shù)據(jù)從控制器傳遞給視圖。 稍后在本教程中,我們將使用視圖模型將數(shù)據(jù)從控制器傳遞給視圖。 傳遞數(shù)據(jù)的視圖模型方法通常比 ViewData 字典方法更為優(yōu)先。 有關(guān)詳細(xì)信息,請參閱何時使用 ViewBag、ViewData 或 TempData。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號