练习 - 添加新的 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 - 随附的
PageModel
类
- 将两个文件存储在项目的 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。
在包含
navbar-nav
类的<ul>
元素中(从第 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(); } }
在上述代码中:
- 已创建名为
_service
的专用只读PizzaService
。 此变量将保存对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 以重新加载具有已注册服务和PizzaListModel
的新构造函数的应用。
显示披萨列表
现在,可在页面上访问披萨列表,接下来需要使用该列表在页面上显示披萨。
打开 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>
元素来保存表格标题。 <tbody>
中的@foreach
语句循环访问披萨列表。Model
属性引用在代码隐藏文件中创建的PizzaListModel
对象。PizzaList
属性引用在代码隐藏文件中定义的PizzaList
属性。
@foreach
语句的每个迭代都会创建一个<tr>
元素来保存披萨数据:- Razor 语法用于显示
<td>
元素中的披萨数据。 此语法用于显示存储在pizza
变量中的Pizza
对象的属性。 Price
是使用 C# 字符串内插进行格式设置的。- 三元表达式用于显示
IsGlutenFree
属性的值(“✔️”或空白单元格)。 - 已创建表单来删除披萨。
asp-page-handler
属性指示应将表单提交到代码隐藏文件中的Delete
处理程序。 你将在后面的单元中创建该处理程序。asp-route-id
属性指示应将Pizza
对象的Id
属性传递给Delete
处理程序。
- Razor 语法用于显示
- 已创建
保存文件。 在浏览器中,“披萨列表”页面会刷新以显示披萨列表。 如果使用的是 GitHub Codespaces,则文件会自动保存,但需要手动刷新浏览器选项卡。
做得很好! 你已创建一个显示披萨列表的 Razor 页面。 在下一单元中,你将了解标记帮助程序和页面处理程序。