列表页
Pages/Movies/Index.cshtml.cs
Razor 页面派生自 PageModel。 按照约定,PageModel
派生的类称为 PageNameModel
。 例如,“索引”页命名为 IndexModel。
这里使用IndexModel的构造函数,通过依赖注入的方式,将数据上下文对象StandardCoreStudyContext添加到页面中。
功能还是挺简单的,就是在页面被get请求时异步请求数据库中的Movie表获取电影数据并赋值给页面的集合对象 Movie。
namespace StandardCoreStudy.Pages.Movies { public class IndexModel : PageModel { private readonly StandardCoreStudy.Data.StandardCoreStudyContext _context; public IndexModel(StandardCoreStudy.Data.StandardCoreStudyContext context) { _context = context; } public IList<Movie> Movie { get;set; } = default!; public async Task OnGetAsync() { if (_context.Movie != null) { Movie = await _context.Movie.ToListAsync(); } } } }
Pages/Movies/Index.cshtml
将页面异步获取到的Movie集合,循环显示出来。
@page @model StandardCoreStudy.Pages.Movies.IndexModel @{ ViewData["Title"] = "Index"; } <h1>Index</h1> <p> <a asp-page="Create">Create New</a> </p> <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.Movie[0].Title) </th> <th> @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.Movie[0].Genre) </th> <th> @Html.DisplayNameFor(model => model.Movie[0].Price) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model.Movie) { <tr> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.ReleaseDate) </td> <td> @Html.DisplayFor(modelItem => item.Genre) </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>
介绍几个常用指令
@page:指令将文件转换为一个 MVC 操作,这意味着它可以处理请求,@page必须是页面上的第一个 Razor 指令。
@model:指令可以指定传递到页面上的模型类型,比如本例中 @model StandardCoreStudy.Pages.Movies.IndexModel 这样。
@Html.DisplayNameFor:获取模型的属性名称,@Html.DisplayNameFor(model => model.Movie[0].Title) 表示 获取这个页面 对象中的Movie集合项的Title属性的名称。
@Html.DisplayFor:获取模型的属性值,@Html.DisplayFor(modelItem => item.Title) 表示获取Title属性的值。
需要注意的是,DisplayNameFor 是 检查 Lambda 表达式(而非求值),因此当没有数据的时候,不会model,model.Movie[0],model.Movie[0].Title这些不会因为null而报错,而DisplayFor需要求值,所以放在循环中使用。
新建页
Create.cshtml.cs
OnGet
方法初始化页面所需的任何状态。 “创建”页没有任何要初始化的状态,因此返回 Page
。 Page
方法创建用于呈现 Create.cshtml
页的 PageResult
对象。
Movie
属性使用 [BindProperty] 特性来选择加入模型绑定。 当“创建”表单发布表单值时,ASP.NET Core 运行时将发布的值绑定到 Movie
模型。
当页面发布表单数据时,运行 OnPostAsync
方法
namespace StandardCoreStudy.Pages.Movies { public class CreateModel : PageModel { private readonly StandardCoreStudy.Data.StandardCoreStudyContext _context; public CreateModel(StandardCoreStudy.Data.StandardCoreStudyContext context) { _context = context; } public IActionResult OnGet() { return Page(); } [BindProperty] public Movie Movie { get; set; } = default!; // To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid || _context.Movie == null || Movie == null) { return Page(); } _context.Movie.Add(Movie); await _context.SaveChangesAsync(); return RedirectToPage("./Index"); } } }
如果没有错误,则将Movie对象写入数据库,并跳转到列表页。
Razor页面部分 Create.cshtml
@page @model StandardCoreStudy.Pages.Movies.CreateModel @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Movie</h4> <hr /> <div class="row"> <div class="col-md-4"> <form method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Movie.Title" class="control-label"></label> <input asp-for="Movie.Title" class="form-control" /> <span asp-validation-for="Movie.Title" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.ReleaseDate" class="control-label"></label> <input asp-for="Movie.ReleaseDate" class="form-control" /> <span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.Genre" class="control-label"></label> <input asp-for="Movie.Genre" class="form-control" /> <span asp-validation-for="Movie.Genre" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Movie.Price" class="control-label"></label> <input asp-for="Movie.Price" class="form-control" /> <span asp-validation-for="Movie.Price" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> <div> <a asp-page="Index">Back to List</a> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
<form method="post">
元素是一个表单标记帮助程序。 表单标记帮助程序会自动包含防伪令牌。
基架引擎在模型中为每个字段(ID 除外)创建 Razor 标记,如下所示
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group"> <label asp-for="Movie.Title" class="control-label"></label> <input asp-for="Movie.Title" class="form-control" /> <span asp-validation-for="Movie.Title" class="text-danger"></span> </div>
验证标记帮助程序(<div asp-validation-summary
和 <span asp-validation-for
)显示验证错误。
标签标记帮助程序 (<label asp-for="Movie.Title" class="control-label"></label>
) 生成标签描述和 Title
属性的 [for]
特性。
输入标记帮助程序 (<input asp-for="Movie.Title" class="form-control">
) 使用 DataAnnotations 属性并在客户端生成 jQuery 验证所需的 HTML 属性。