将视图添加到 ASP.NET Core MVC 应用Add a view to an ASP.NET Core MVC app

在本部分中,将修改 类,进而使用 Razor 视图文件来顺利封装为客户端生成 HTML 响应的过程。

使用 Razor 创建视图模板文件。基于 Razor 的模板具有“.cshtml”文件扩展名 。它们提供了一种巧妙的方法来使用 C# 创建 HTML 输出。

当前,Index 方法返回带有在控制器类中硬编码的消息的字符串。HelloWorldController 类中,将 Index 方法替换为以下代码:

上面的代码调用控制器的 方法。它使用视图模板来生成 HTML 响应。控制器方法(亦称为“操作方法” ,如上面的 Index 方法)通常返回 IActionResult(或派生自 的类),而不是 string 等类型。

  • 右键单击“视图”文件夹,然后单击“添加”>“新文件夹”,并将文件夹命名为“HelloWorld”。

  • 右键单击“Views/HelloWorld”文件夹,然后单击“添加”>“新项”。

  • 在“添加新项 - MvcMovie”对话框中

    • 在右上角的搜索框中,输入“视图”

    • 选择“Razor 视图”

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

    • 选择“添加”

HelloWorldController 添加 Index 视图。

  • 添加一个名为“Views/HelloWorld”的新文件夹。
  • 向 Views/HelloWorld 文件夹添加名为“Index.cshtml”的新文件。
  • 右键单击“视图”文件夹,然后单击“添加”>“新文件夹”,并将文件夹命名为“HelloWorld”。

  • 右键单击“Views/HelloWorld”文件夹,然后单击“添加”>“新文件” 。

  • 在“新建文件”对话框中 :

    • 在左侧窗格中,选择“ASP.NET Core” 。
    • 在中间窗格中,选择“MVC 视图页面” 。
    • 在“名称”框中键入“Index” 。
    • 选择“新建” 。

“添加新项”对话框

使用以下内容替换 Razor 视图文件 Views/HelloWorld/Index.cshtml 的内容 :

  1. @{
  2. ViewData["Title"] = "Index";
  3. }
  4. <h2>Index</h2>
  5. <p>Hello from our View Template!</p>

导航到 HelloWorldController 中的 Index 方法作用不大;它运行 return View(); 语句,指定此方法应使用视图模板文件来呈现对浏览器的响应。由于未指定视图模板文件名称,MVC 默认使用默认视图文件。默认视图文件具有与方法 (Index) 相同的名称,因此在 /Views/HelloWorld/Index.cshtml 中使用。下面图片显示了视图中硬编码的字符串“Hello from our View Template!”

更改视图和布局页面Change views and layout pages

选择菜单链接(“MvcMovie”、“首页”和“隐私”) 。每页显示相同的菜单布局。菜单布局是在 Views/Shared/_Layout.cshtml 文件中实现的 。打开 Views/Shared/_Layout.cshtml 文件 。

模板使你能够在一个位置指定网站的 HTML 容器布局,然后将它应用到网站中的多个页面。查找 @RenderBody() 行。RenderBody 是显示创建的所有特定于视图的页面的占位符,已包装在布局页面中 。例如,如果选择“隐私”链接,Views/Home/Privacy.cshtml 视图将在 RenderBody 方法中呈现 。

将 Views/Shared/_Layout.cshtml 文件的内容替换为以下标记。 突出显示所作更改:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>@ViewData["Title"] - Movie App</title>
  7. <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
  8. <link rel="stylesheet" href="~/css/site.css" />
  9. </head>
  10. <body>
  11. <header>
  12. <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
  13. <div class="container">
  14. <a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
  15. <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
  16. aria-expanded="false" aria-label="Toggle navigation">
  17. <span class="navbar-toggler-icon"></span>
  18. </button>
  19. <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
  20. <ul class="navbar-nav flex-grow-1">
  21. <li class="nav-item">
  22. <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
  23. </li>
  24. <li class="nav-item">
  25. <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
  26. </li>
  27. </ul>
  28. </div>
  29. </nav>
  30. </header>
  31. <div class="container">
  32. <main role="main" class="pb-3">
  33. @RenderBody()
  34. </main>
  35. </div>
  36. <footer class="border-top footer text-muted">
  37. <div class="container">
  38. &copy; 2020 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
  39. </div>
  40. </footer>
  41. <script src="~/lib/jquery/dist/jquery.min.js"></script>
  42. <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
  43. <script src="~/js/site.js" asp-append-version="true"></script>
  44. @RenderSection("Scripts", required: false)
  45. </body>
  46. </html>

上述标记进行以下更改:

  • MvcMovie 更改为 Movie App 3 次。
  • 定位点元素 <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>

在前面的标记中,省略了 asp-area="" 定位点标记帮助程序属性和属性值,因为此应用未使用。

说明Movies 控制器尚未实现。此时,Movie App 链接不起作用。

保存更改并选择“隐私”链接 。请注意浏览器选项卡上的标题现在显示的是“隐私策略 - 电影应用” ,而不是“隐私策略 - Mvc 电影” :

“隐私”选项卡

选择“主页”链接,请注意,标题和定位文本还会显示“电影应用” 。我们能够在布局模板中进行一次更改,让网站上的所有页面都反映新的链接文本和新标题。

检查 Views/_ViewStart.cshtml 文件 :

  1. @{
  2. Layout = "_Layout";
  3. }

Views/_ViewStart.cshtml 文件将 Views/Shared/_Layout.cshtml 文件引入到每个视图中 。可以使用 Layout 属性设置不同的布局视图,或将它设置为 ,这样将不会使用任何布局文件。

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

  1. @{
  2. ViewData["Title"] = "Movie List";
  3. }
  4. <h2>My Movie List</h2>
  5. <p>Hello from our View Template!</p>

稍稍对标题和 <h2> 元素进行一些更改,这样可以看出哪一段代码更改了显示。

保存更改并导航到 https://localhost:{PORT}/HelloWorld请注意,浏览器标题、主标题和辅助标题已更改。(如果没有在浏览器中看到更改,则可能正在查看缓存的内容。在浏览器中按 Ctrl + F5 强制加载来自服务器的响应。)浏览器标题是使用我们在 Index.cshtml 视图模板中设置的 ViewData["Title"] 以及在布局文件中添加的额外“ - Movie App”创建的 。

Index.cshtml 视图模板中的内容与 Views/Shared/_Layout.cshtml 视图模板合并 。单个 HTML 响应将发送到浏览器。凭借布局模板可以轻松地对应用中所有页面进行更改。若要了解更多信息,请参阅。

但我们这一点点“数据”(在此示例中为“Hello from our View Template!”消息)是硬编码的。MVC 应用程序有一个“V”(视图),而你已有一个“C”(控制器),但还没有“M”(模型)。

将数据从控制器传递给视图Passing Data from the Controller to the View

控制器操作会被调用以响应传入的 URL 请求。控制器类是编写处理传入浏览器请求的代码的地方。控制器从数据源检索数据,并决定将哪些类型的响应发送回浏览器。可以从控制器使用视图模板来生成并格式化对浏览器的 HTML 响应。

控制器负责提供所需的数据,使视图模板能够呈现响应。最佳做法:视图模板不应该直接执行业务逻辑或与数据库进行交互 。相反,视图模板应仅使用由控制器提供给它的数据。保持此“分离关注点”有助于保持代码干净以及可测试性和可维护性。

目前,HelloWorldController 类中的 Welcome 方法采用 nameID 参数,然后将值直接输出到浏览器。应将控制器更改为使用视图模板,而不是使控制器将此响应呈现为字符串。视图模板会生成动态响应,这意味着必须将适当的数据位从控制器传递给视图以生成响应。为此,可以让控制器将视图模板所需的动态数据(参数)放置在视图模板稍后可以访问的 ViewData 字典中。

在 HelloWorldController.cs 中,更改 Welcome 方法以将 MessageNumTimes 值添加到 ViewData 字典 。ViewData 字典是一个动态对象,这意味着可以使用任何类型;只有将内容放在其中后 ViewData 对象才具有定义的属性。自动将命名参数(namenumTimes)从地址栏中的查询字符串映射到方法中的参数。完整的 HelloWorldController.cs 文件如下所示 :

  1. using Microsoft.AspNetCore.Mvc;
  2. using System.Text.Encodings.Web;
  3. namespace MvcMovie.Controllers
  4. {
  5. public class HelloWorldController : Controller
  6. {
  7. public IActionResult Index()
  8. {
  9. return View();
  10. }
  11. public IActionResult Welcome(string name, int numTimes = 1)
  12. {
  13. ViewData["Message"] = "Hello " + name;
  14. ViewData["NumTimes"] = numTimes;
  15. return View();
  16. }
  17. }
  18. }

ViewData 字典对象包含将传递给视图的数据。

创建一个名为 Views/HelloWorld/Welcome.cshtml 的 Welcome 视图模板 。

在 Welcome.cshtml 视图模板中创建一个循环,显示“Hello” NumTimes使用以下内容替换 Views/HelloWorld/Welcome.cshtml 的内容 :

  1. @{
  2. ViewData["Title"] = "Welcome";
  3. }
  4. <h2>Welcome</h2>
  5. <ul>
  6. @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
  7. {
  8. <li>@ViewData["Message"]</li>
  9. }

保存更改并浏览到以下 URL:

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

数据取自 URL,并传递给使用 的控制器。控制器将数据打包到 ViewData 字典中,并将该对象传递给视图。然后,视图将数据作为 HTML 呈现给浏览器。

“隐私”视图,显示了 Welcome 标签以及四个“Hello Rick”短语

在上面的示例中,我们使用 ViewData 字典将数据从控制器传递给视图。稍后在本教程中,我们将使用视图模型将数据从控制器传递给视图。传递数据的视图模型方法通常比 ViewData 字典方法更为优先。有关详细信息,请参阅何时使用 ViewBag、ViewData 或 TempData

在下一个教程中,将创建电影数据库。

下一页

在本部分中,将修改 HelloWorldController 类,进而使用 视图文件来顺利封装为客户端生成 HTML 响应的过程。

使用 Razor 创建视图模板文件。基于 Razor 的模板具有“.cshtml”文件扩展名 。它们提供了一种巧妙的方法来使用 C# 创建 HTML 输出。

当前,Index 方法返回带有在控制器类中硬编码的消息的字符串。HelloWorldController 类中,将 Index 方法替换为以下代码:

  1. public IActionResult Index()
  2. {
  3. return View();
  4. }

上面的代码调用控制器的 View 方法。它使用视图模板来生成 HTML 响应。控制器方法(亦称为“操作方法” ,如上面的 Index 方法)通常返回 (或派生自 ActionResult 的类),而不是 string 等类型。

  • 右键单击“视图”文件夹,然后单击“添加”>“新文件夹”,并将文件夹命名为“HelloWorld”。

  • 右键单击“Views/HelloWorld”文件夹,然后单击“添加”>“新项”。

  • 在“添加新项 - MvcMovie”对话框中

    • 在右上角的搜索框中,输入“视图”

    • 选择“Razor 视图”

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

    • 选择“添加”

HelloWorldController 添加 Index 视图。

  • 添加一个名为“Views/HelloWorld”的新文件夹。
  • 向 Views/HelloWorld 文件夹添加名为“Index.cshtml”的新文件。
  • 右键单击“视图”文件夹,然后单击“添加”>“新文件夹”,并将文件夹命名为“HelloWorld”。

  • 右键单击“Views/HelloWorld”文件夹,然后单击“添加”>“新文件” 。

    • 在左窗格中,选择“Web” 。
    • 在中间窗格中,选择“空 HTML 文件” 。
    • 在“名称”框中键入“Index.cshtml” 。
    • 选择“新建” 。

“添加新项”对话框

使用以下内容替换 Razor 视图文件 Views/HelloWorld/Index.cshtml 的内容 :

  1. @{
  2. }
  3. <h2>Index</h2>
  4. <p>Hello from our View Template!</p>

导航到 https://localhost:{PORT}/HelloWorldHelloWorldController 中的 Index 方法作用不大;它运行 return View(); 语句,指定此方法应使用视图模板文件来呈现对浏览器的响应。由于未指定视图模板文件名称,MVC 默认使用默认视图文件。默认视图文件具有与方法 (Index) 相同的名称,因此在 /Views/HelloWorld/Index.cshtml 中使用。下面图片显示了视图中硬编码的字符串“Hello from our View Template!”

更改视图和布局页面Change views and layout pages

选择菜单链接(“MvcMovie”、“首页”和“隐私”) 。每页显示相同的菜单布局。菜单布局是在 Views/Shared/_Layout.cshtml 文件中实现的 。打开 Views/Shared/_Layout.cshtml 文件 。

布局模板使你能够在一个位置指定网站的 HTML 容器布局,然后将它应用到网站中的多个页面。查找 @RenderBody() 行。RenderBody 是显示创建的所有特定于视图的页面的占位符,已包装在布局页面中 。例如,如果选择“隐私”链接,Views/Home/Privacy.cshtml 视图将在 RenderBody 方法中呈现 。

  • 在标题和页脚元素中,将 MvcMovie 更改为 Movie App
  • 将定位点元素 <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>

下列标记显示了突出显示的更改:

在前面的标记中,省略了 asp-area ,因为此应用未使用区域

说明Movies 控制器尚未实现。此时,Movie App 链接不起作用。

保存更改并选择“隐私”链接 。请注意浏览器选项卡上的标题现在显示的是“隐私策略 - 电影应用” ,而不是“隐私策略 - Mvc 电影” :

“隐私”选项卡

选择“主页”链接,请注意,标题和定位文本还会显示“电影应用” 。我们能够在布局模板中进行一次更改,让网站上的所有页面都反映新的链接文本和新标题。

检查 Views/_ViewStart.cshtml 文件 :

  1. @{
  2. Layout = "_Layout";
  3. }

Views/_ViewStart.cshtml 文件将 Views/Shared/_Layout.cshtml 文件引入到每个视图中 。可以使用 Layout 属性设置不同的布局视图,或将它设置为 null,这样将不会使用任何布局文件。

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

  1. @{
  2. ViewData["Title"] = "Movie List";
  3. }
  4. <h2>My Movie List</h2>
  5. <p>Hello from our View Template!</p>

稍稍对标题和 <h2> 元素进行一些更改,这样可以看出哪一段代码更改了显示。

上述代码中的 ViewData["Title"] = "Movie List";ViewData 字典的 Title 属性设置为“Movie List”。Title 属性在布局页面中的 <title> HTML 元素中使用:

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

保存更改并导航到 请注意,浏览器标题、主标题和辅助标题已更改。(如果没有在浏览器中看到更改,则可能正在查看缓存的内容。在浏览器中按 Ctrl + F5 强制加载来自服务器的响应。)浏览器标题是使用我们在 Index.cshtml 视图模板中设置的 ViewData["Title"] 以及在布局文件中添加的额外“ - Movie App”创建的 。

还要注意,Index.cshtml 视图模板中的内容是如何与 Views/Shared/_Layout.cshtml 视图模板合并的,并且注意单个 HTML 响应被发送到了浏览器 。凭借布局模板可以很容易地对应用程序中所有页面进行更改。若要了解更多信息,请参阅布局

但我们这一点点“数据”(在此示例中为“Hello from our View Template!”消息)是硬编码的。MVC 应用程序有一个“V”(视图),而你已有一个“C”(控制器),但还没有“M”(模型)。

将数据从控制器传递给视图Passing Data from the Controller to the View

控制器操作会被调用以响应传入的 URL 请求。控制器类是编写处理传入浏览器请求的代码的地方。控制器从数据源检索数据,并决定将哪些类型的响应发送回浏览器。可以从控制器使用视图模板来生成并格式化对浏览器的 HTML 响应。

控制器负责提供所需的数据,使视图模板能够呈现响应。最佳做法:视图模板不应该直接执行业务逻辑或与数据库进行交互 。相反,视图模板应仅使用由控制器提供给它的数据。保持此“分离关注点”有助于保持代码干净以及可测试性和可维护性。

目前,HelloWorldController 类中的 Welcome 方法采用 nameID 参数,然后将值直接输出到浏览器。应将控制器更改为使用视图模板,而不是使控制器将此响应呈现为字符串。视图模板会生成动态响应,这意味着必须将适当的数据位从控制器传递给视图以生成响应。为此,可以让控制器将视图模板所需的动态数据(参数)放置在视图模板稍后可以访问的 ViewData 字典中。

在 HelloWorldController.cs 中,更改 Welcome 方法以将 MessageNumTimes 值添加到 ViewData 字典 。ViewData 字典是一个动态对象,这意味着可以使用任何类型;只有将内容放在其中后 ViewData 对象才具有定义的属性。MVC 模型绑定系统自动将命名参数(namenumTimes)从地址栏中的查询字符串映射到方法中的参数。完整的 HelloWorldController.cs 文件如下所示 :

  1. using Microsoft.AspNetCore.Mvc;
  2. using System.Text.Encodings.Web;
  3. namespace MvcMovie.Controllers
  4. {
  5. public class HelloWorldController : Controller
  6. {
  7. public IActionResult Index()
  8. {
  9. return View();
  10. }
  11. public IActionResult Welcome(string name, int numTimes = 1)
  12. {
  13. ViewData["Message"] = "Hello " + name;
  14. ViewData["NumTimes"] = numTimes;
  15. return View();
  16. }
  17. }

ViewData 字典对象包含将传递给视图的数据。

创建一个名为 Views/HelloWorld/Welcome.cshtml 的 Welcome 视图模板 。

在 Welcome.cshtml 视图模板中创建一个循环,显示“Hello” NumTimes使用以下内容替换 Views/HelloWorld/Welcome.cshtml 的内容 :

保存更改并浏览到以下 URL:

数据取自 URL,并传递给使用 MVC 模型绑定器的控制器。控制器将数据打包到 ViewData 字典中,并将该对象传递给视图。然后,视图将数据作为 HTML 呈现给浏览器。

“隐私”视图,显示了 Welcome 标签以及四个“Hello Rick”短语

在上面的示例中,我们使用 ViewData 字典将数据从控制器传递给视图。稍后在本教程中,我们将使用视图模型将数据从控制器传递给视图。传递数据的视图模型方法通常比 字典方法更为优先。有关详细信息,请参阅。

在下一个教程中,将创建电影数据库。