练习 - 添加新的 Razor 页面
在上一单元中,你获取了 Contoso Pizza 项目的源代码,然后对主页进行了一些简单的更改。 在本单元中,你将向项目添加新的 Razor 页面。
创建“披萨列表”页面
若要创建新的 Razor 页面,需使用 .NET CLI。
由于终端被
dotnet watch命令阻止,因此请通过右键单击“资源管理器”中的 ContosoPizza 文件夹以打开另一个终端,然后选择“在集成终端中打开”。在新的终端窗口中,输入以下命令:
dotnet new page --name PizzaList --namespace ContosoPizza.Pages --output Pages上述命令:
- 在
ContosoPizza.Pages命名空间中创建下面这两个文件:- PizzaList.cshtml - Razor 页面
- PizzaList.cshtml.cs - 随附的 类
- 将两个文件存储在项目的 Pages 子目录中。
- 在
在 Pages/PizzaList.cshtml 中,在 代码块中添加以下代码:
ViewData["Title"] = "Pizza List 🍕";这会设置页面的
<title>元素。在文件末尾添加以下代码:
<h1>Pizza List 🍕</h1> <!-- New Pizza form will go here --> <!-- List of pizzas will go here -->这会向页面添加一个标题,以及两个 HTML 注释占位符,用于稍后将添加的功能。
保存文件。 如果使用的是 GitHub Codespaces,则文件会自动保存。
返回到正在运行
dotnet watch的终端,然后选择 Ctrl+R 以重新加载应用并检测新文件。
将“披萨列表”页面添加到导航菜单
这将是测试此页面的好时机,但无法在浏览器中访问此页面,因为尚未在导航菜单中链接它。 你现在将链接它。
打开 Pages/Shared/_Layout.cshtml。
在包含
<ul>类的navbar-nav元素中(从第 21 行开始),请注意包含指向“主页”和“隐私”页面的链接的<li>元素。 将以下代码添加到列表末尾处包含“隐私”链接的<li>元素的后面:<li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/PizzaList">Pizza List 🍕</a> </li>这会向导航菜单添加一个指向 PizzaList 页面的链接。
保存文件。 包含应用的浏览器选项卡会自动刷新以显示更改。 如果使用的是 GitHub Codespaces,则文件会自动保存,但需要手动刷新浏览器选项卡。
在导航菜单中选择“披萨列表 🍕”链接。 随即会显示“披萨列表”页面。
向依赖项注入容器注册 PizzaService 类
“披萨列表”页依赖于 PizzaService 对象来检索披萨列表。 你将使用依赖项注入向页面提供 PizzaService 对象。 首先,将 PizzaService 类注册到容器。
打开 Program.cs。
在将服务添加到容器的部分中,添加以下代码:
builder.Services.AddScoped<PizzaService>();此代码向依赖项注入容器注册
PizzaService类。AddScoped方法指示应为每个 HTTP 请求创建新的PizzaService对象。 现在可以将PizzaService注入到任何 Razor 页面。保存文件。 如果使用的是 GitHub Codespaces,则文件会自动保存。
显示披萨列表
让我们来修改“披萨列表”页面的 PageModel 类,以从 PizzaService 对象检索披萨列表并将其存储在属性中。
打开 Pages/PizzaList.cshtml.cs。
将下列
using语句添加到文件顶部:using ContosoPizza.Models; using ContosoPizza.Services;这些语句可导入你将在页面中使用的
Pizza和PizzaService类型。在
ContosoPizza.Pages命名空间块中,将整个PizzaListModel类替换为以下代码:public class PizzaListModel : PageModel { private readonly PizzaService _service; public IList<Pizza> PizzaList { get;set; } = default!; public PizzaListModel(PizzaService service) { _service = service; } public void OnGet() { PizzaList = _service.GetPizzas(); } }在上述代码中:
- 已创建名为
PizzaService的专用只读_service。 此变量将保存对PizzaService对象的引用。-
readonly关键字指示在构造函数中设置_service变量的值之后无法对其进行更改。
-
- 定义
PizzaList属性以保存披萨列表。-
IList<Pizza>类型指示PizzaList属性将保存Pizza对象列表。 -
PizzaList被初始化为default!,以向编译器表明它稍后将被初始化,因此不需要进行 null 安全性检查。
-
- 构造函数接受
PizzaService对象。- 对象
PizzaService通过依赖项注入提供。
- 对象
- 定义
OnGet方法以从PizzaService对象中检索披萨列表并将其存储在PizzaList属性中。
提示
如果需要了解 null 安全性方面的帮助,请参阅 C# 中的 Null 安全。
- 已创建名为
保存文件。 如果使用的是 GitHub Codespaces,则文件会自动保存。
返回到正在运行
dotnet watch的终端,然后按 Ctrl+R 以重新加载具有已注册服务和 的新构造函数的应用。
显示披萨列表
现在,可在页面上访问披萨列表,接下来需要使用该列表在页面上显示披萨。
打开 Pages/PizzaList.cshtml。
使用下面的代码替换
<!-- List of pizzas will go here -->注释:<table class="table mt-5"> <thead> <tr> <th scope="col">Name</th> <th scope="col">Price</th> <th scope="col">Size</th> <th scope="col">Gluten Free</th> <th scope="col">Delete</th> </tr> </thead> <tbody> @foreach (var pizza in Model.PizzaList) { <tr> <td>@pizza.Name</td> <td>@($"{pizza.Price:C}")</td> <td>@pizza.Size</td> <td>@(pizza.IsGlutenFree ? "✔️" : string.Empty)</td> <td> <form method="post" asp-page-handler="Delete" asp-route-id="@pizza.Id"> <button class="btn btn-danger">Delete</button> </form> </td> </tr> } </tbody> </table>在上述代码中:
- 已创建
<table>元素来显示披萨列表。 - 已创建
<thead>元素来保存表格标题。 -
@foreach中的<tbody>语句循环访问披萨列表。-
Model属性引用在代码隐藏文件中创建的PizzaListModel对象。 -
PizzaList属性引用在代码隐藏文件中定义的PizzaList属性。
-
-
@foreach语句的每个迭代都会创建一个<tr>元素来保存披萨数据:- Razor 语法用于显示
<td>元素中的披萨数据。 此语法用于显示存储在Pizza变量中的pizza对象的属性。 -
Price是使用 C# 字符串内插进行格式设置的。 - 三元表达式用于显示
IsGlutenFree属性的值(“✔️”或空白单元格)。 - 已创建表单来删除披萨。
-
asp-page-handler属性指示应将表单提交到代码隐藏文件中的Delete处理程序。 你将在后面的单元中创建该处理程序。 -
asp-route-id属性指示应将Id对象的Pizza属性传递给Delete处理程序。
-
- Razor 语法用于显示
- 已创建
保存文件。 在浏览器中,“披萨列表”页面会刷新以显示披萨列表。 如果使用的是 GitHub Codespaces,则文件会自动保存,但需要手动刷新浏览器选项卡。
做得很好! 你已创建一个显示披萨列表的 Razor 页面。 在下一单元中,你将了解标记帮助程序和页面处理程序。