学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面
学习ASP.NET Core Razor 编程系列目录
学习ASP.NET Core Razor 编程系列二——添加一个实体
学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面
本篇文章介绍上一篇文章中创建的书籍信息管理系统中增删改查的四个Razor模板页面。
一、列表页面。
我们首先来了解一下书籍列表页面,这个页面位置在 Pages/Books/Index.cshtml.cs :
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using RazorMvcBooks.Models; namespace RazorMvcBooks.Pages.Books { public class IndexModel : PageModel { private readonly RazorMvcBooks.Models.BookContext _context; public IndexModel(RazorMvcBooks.Models.BookContext context) { _context = context; } public IList<Book> Book { get;set; } public async Task OnGetAsync() { Book = await _context.Book.ToListAsync(); } } }
列表页面IndexModel派生自 PageModel。 按照命名规则PageModel 的派生类一般命名为 <PageName>Model。 构造函数使用依赖关系注入的方式将 BookContext 添加到页面。 所有通过上一文章中的方法创建的模板页面都是如此。
当Index页面发出请求时,OnGetAsync 方法向 Razor 页面返回一个书籍列表。 在 Razor 页面上调用 OnGetAsync 方法或 OnGet方法初始化页面数据。 在本示例中,OnGetAsync 将数据库中Book表中的所有书籍信息,并以列表的形式显示出来。
当 OnGet 方法返回 void 或 OnGetAsync方法返回 Task 时,不需要任何返回语句。 当返回类型是 IActionResult 或 Task<IActionResult> 时,必须提供返回语句。
下面我们介绍一下有返回的方法,例如 Pages/Movies/Create.cshtml.cs 页面中的OnPostAsync方法,代码如下:
public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } _context.Book.Add(Book); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); }
其次,我们来看看书籍列表页面中的前端代码,这个页面位置在 Pages/Books/Index.cshtml,在Visual Studio 2017中使用鼠标左键双击打开 页面,代码如下:
@page @model RazorMvcBooks.Pages.Books.IndexModel @{ ViewData["Title"] = "Index"; } <h2>Index</h2> <p> <a asp-page="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.Book[0].Name) </th> <th> @Html.DisplayNameFor(model => model.Book[0].ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.Book[0].Author) </th> <th> @Html.DisplayNameFor(model => model.Book[0].Price) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model.Book) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Author) </td> <td> @Html.DisplayFor(modelItem => item.Price) </td> <td> <a asp-page="./Edit" asp-route-id="@item.ID">Edit</a> | <a asp-page="./Details" asp-route-id="@item.ID">Details</a> | <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a> </td> </tr> } </tbody> </table>
Razor指令可以根据规则从 HTML 转换为 C# 或 Razor 特定标记。 当在 @ 符号后跟 Razor 保留关键字时,它会转换为 Razor 特定标记,如果不是Razor保留关键字,则会转换为 C#。
@page Razor 指令将文件转换为一个 MVC 操作,这意味着它可以处理请求。 @page 必须是页面上的第一个 Razor 指令。 @page 是转换成 Razor 特定标记的一个示例。
请查看下列HTML助手中使用的lambda表达式:
@Html.DisplayNameFor(model => model.Book[0].Name)
DisplayNameFor HTML辅助助手检查 Lambda 表达式中引用的Name属性来确定显示名称。 Lambda表达式是检查而不是求值。 这意味着当 model、model.Book 或 model.Book[0] 为 null 或为空时,不会存在任何访问冲突。 当使用Html辅助助手取值辅助方法对 Lambda 表达式取值(例如,使用 @Html.DisplayFor(modelItem => item.Title)),将取得该实体的属性值。
@model指令
@page
@model RazorMvcBooks.Pages.Books.IndexModel
@model 指令指定传递给 Razor 页面的实体类型。在上面的示例中,@model 使 PageModel 派生的类IndexModel可用于 Razor 页面。 在页面上通过 @Html.DisplayNameFor 和 @Html.DisplayName HTML 辅助助手使用该实体。
ViewData 和布局
首先,我们看一下下面的布局代码:
@page
@model RazorMvcBooks.Pages.Books.IndexModel
@{
ViewData["Title"] = "Index";
}
上面的代码就是 Razor 代码转换为 C# 的一个示例。 大括号“{ }” 字符括住 C# 代码块。
PageModel 基类具有 ViewData 字典属性,可用于添加要传递到某个视图的数据。 可以使用键/值模式将对象添加到 ViewData 字典。 在上面的示例中,“Title”属性被添加到 ViewData 字典中。 “Title”属性的在 Pages/_Layout.cshtml 文件中使用。
你可以在Visual Studio 2017中打开 位于 Pages/_Layout.cshtml 文件,我们来看看这个文件中的前几行,便可以发现 “Title”的使用。代码如下。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - RazorMvcBooks</title> <environment include="Development"> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" /> <link rel="stylesheet" href="~/css/site.css" /> </environment> @*Markup removed for brevity.*@
行 @*Markup removed for brevity.*@ 为 Razor 注释。 与 HTML 注释不同 (<!-- -->),Razor 注释不会发送到客户端。
在Visual Studio 2017 中按F5运行应用程序,在浏览器测试项目中的链接(Home、About、Contact、Create、Edit和Delete)。你会发现在浏览器中每个页面的标题都是一样的。当您将某个页面添加到书签时,标题用于这个书签。 Pages/Index.cshtml 和 Pages/Books/Index.cshtml 当前具有相同的标题,但可以修改它们以具有不同的值。
我们可以在Visual Studio 2017中打开 位于 Pages/_ViewStart.cshtml 文件,查看其中的 Layout 属性,如下代码:
@{
Layout = "_Layout";
}
上面的标记将所有 Razor 页面的布局设置为 Pages 文件夹下的 Pages/_Layout.cshtml所定义的布局。
修改布局
第一步,我们要使用“书籍管理系统”来替换 Pages/_Layout.cshtml 文件中的 <title> 元素中的RazorMvcBooks字符串。如下代码。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] – 书籍管理系统</title>
第二步,在 Pages/_Layout.cshtml 文件中的找到以下数据信息:
<a asp-page="/Index" class="navbar-brand">RazorMvcBooks</a>
将上面的数据信息替换为以下数据信息:
<a asp-page="/Books/Index" class="navbar-brand">书籍管理系统</a>
上面的<a>元素是一个标记辅助助手。此处它是<a>标记辅助助手。asp-page="/Books/Index" 标记辅助助手属性和值可以用来创建指向 /Books/Index Razor 页面的链接。
保存所做的修改,在Visual Studio 2017中按F5运行程序,在浏览器中通过单击“书籍管理系统”链接测试应用,如下图。