本教程介紹上一教程中通過搭建基架創(chuàng)建的 Razor 頁面。
查看或下載示例。
檢查 Pages/Movies/Index.cshtml.cs 頁面模型:
C#
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 RazorPagesMovie.Models;
namespace RazorPagesMovie.Pages.Movies
{
public class IndexModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;
public IndexModel(RazorPagesMovie.Models.RazorPagesMovieContext context)
{
_context = context;
}
public IList<Movie> Movie { get;set; }
public async Task OnGetAsync()
{
Movie = await _context.Movie.ToListAsync();
}
}
}
Razor 頁面派生自 PageModel。 按照約定,PageModel 派生的類稱為 <PageName>Model。 此構(gòu)造函數(shù)使用依賴關(guān)系注入將 RazorPagesMovieContext 添加到頁。 所有已搭建基架的頁面都遵循此模式。請參閱異步代碼,了解有關(guān)使用實(shí)體框架的異步編程的詳細(xì)信息。
對頁面發(fā)出請求時(shí),OnGetAsync 方法向 Razor 頁面返回影片列表。 在 Razor 頁面上調(diào)用 OnGetAsync 或 OnGet 以初始化頁面狀態(tài)。 在這種情況下,OnGetAsync 將獲得影片列表并顯示出來。
當(dāng) OnGet 返回 void 或 OnGetAsync 返回 Task 時(shí),不使用任何返回方法。 當(dāng)返回類型是 IActionResult 或 Task<IActionResult> 時(shí),必須提供返回語句。 例如,Pages/Movies/Create.cshtml.cs OnPostAsync 方法:
C#
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
檢查 Pages/Movies/Index.cshtml Razor 頁面:
CSHTML
@page
@model RazorPagesMovie.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>
Razor 可以從 HTML 轉(zhuǎn)換為 C# 或 Razor 特定標(biāo)記。 當(dāng) @ 符號后跟 Razor 保留關(guān)鍵字時(shí),它會轉(zhuǎn)換為 Razor 特定標(biāo)記,否則會轉(zhuǎn)換為 C#。
@page Razor 指令將文件轉(zhuǎn)換為一個(gè) MVC 操作,這意味著它可以處理請求。 @page 必須是頁面上的第一個(gè) Razor 指令。 @page 是轉(zhuǎn)換到 Razor 特定標(biāo)記的一個(gè)示例。 有關(guān)詳細(xì)信息,請參閱 Razor 語法。
檢查以下 HTML 幫助程序中使用的 Lambda 表達(dá)式:
CSHTML
@Html.DisplayNameFor(model => model.Movie[0].Title))
DisplayNameFor HTML 幫助程序檢查 Lambda 表達(dá)式中引用的 Title 屬性來確定顯示名稱。 檢查 Lambda 表達(dá)式(而非求值)。 這意味著當(dāng) model、model.Movie 或 model.Movie[0] 為 null 或?yàn)榭諘r(shí),不會存在任何訪問沖突。 對 Lambda 表達(dá)式求值時(shí)(例如,使用 @Html.DisplayFor(modelItem => item.Title)),將求得該模型的屬性值。
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@model 指令指定傳遞給 Razor 頁面的模型類型。 在前面的示例中,@model 行使 PageModel 派生的類可用于 Razor 頁面。 在頁面上的 @Html.DisplayNameFor 和 @Html.DisplayFor HTML 幫助程序中使用該模型。
選擇菜單鏈接(“RazorPagesMovie”、“主頁”和“隱私”)。 每頁顯示相同的菜單布局。 菜單布局是在 Pages/Shared/_Layout.cshtml 文件中實(shí)現(xiàn)。 打開 Pages/Shared/_Layout.cshtml 文件。
布局模板使你能夠在一個(gè)位置指定網(wǎng)站的 HTML 容器布局,然后將它應(yīng)用到網(wǎng)站中的多個(gè)頁面。 查找 @RenderBody() 行。 RenderBody 是顯示所創(chuàng)建的全部頁面專用視圖的占位符,已包裝在布局頁中。 例如,如果選擇“隱私”鏈接,Pages/Privacy.cshtml 視圖在 RenderBody 方法中呈現(xiàn)。
考慮來自 Pages/Movies/Index.cshtml 文件中的以下代碼:
CSHTML
@page
@model RazorPagesMovie.Pages.Movies.IndexModel
@{
ViewData["Title"] = "Index";
}
前面突出顯示的代碼是 Razor 轉(zhuǎn)換為 C# 的一個(gè)示例。 { 和 } 字符括住 C# 代碼塊。
PageModel 基類具有 ViewData 字典屬性,可用于添加要傳遞到某個(gè)視圖的數(shù)據(jù)。 可以使用鍵/值模式將對象添加到 ViewData 字典。 在前面的示例中,“Title”屬性被添加到 ViewData 字典。
“Title”屬性用于 Pages/Shared/_Layout.cshtml 文件。 以下標(biāo)記顯示 _Layout.cshtml 文件的前幾行。
CSHTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - RazorPagesMovie</title>
@*Markup removed for brevity.*@
行 @*Markup removed for brevity.*@ 是不會出現(xiàn)在布局文件中的 Razor 注釋。 與 HTML 注釋不同 (<!-- -->),Razor 注釋不會發(fā)送到客戶端。
更改 Pages/Shared/_Layout.cshtml 文件中的 <title> 元素以顯示 Movie 而不是 RazorPagesMovie。
CSHTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Movie</title>
在 Pages/Shared/_Layout.cshtml 文件中,查找以下定位點(diǎn)元素。
CSHTML
<a class="navbar-brand" asp-area="" asp-page="/Index">RazorPagesMovie</a>
將前面的元素替換為以下標(biāo)記。
CSHTML
<a class="navbar-brand" asp-page="/Movies/Index">RpMovie</a>
前面的定位點(diǎn)元素是一個(gè)標(biāo)記幫助程序。 此處它是定位點(diǎn)標(biāo)記幫助程序。 asp-page="/Movies/Index"標(biāo)記幫助程序?qū)傩院椭悼梢詣?chuàng)建指向 /Movies/Index Razor 頁面的鏈接。 asp-area 屬性值為空,因此在鏈接中未使用區(qū)域。 有關(guān)詳細(xì)信息,請參閱區(qū)域。
保存所做的更改,并通過單擊“RpMovie”鏈接測試應(yīng)用。 如果遇到任何問題,請參閱 GitHub 中的 _Layout.cshtml 文件。
測試其他鏈接(“主頁”、“RpMovie”、“創(chuàng)建”、“編輯”和“刪除”)。 每個(gè)頁面都設(shè)置有標(biāo)題,可以在瀏覽器選項(xiàng)卡中看到標(biāo)題。將某個(gè)頁面加入書簽時(shí),標(biāo)題用于該書簽。
備注
可能無法在 Price 字段中輸入十進(jìn)制逗號。 若要使 jQuery 驗(yàn)證支持使用逗號(“,”)表示小數(shù)點(diǎn)的的非英語區(qū)域設(shè)置,以及支持非美國英語日期格式,必須執(zhí)行使應(yīng)用全球化的步驟。 有關(guān)添加十進(jìn)制逗號的說明,請參閱 GitHub 問題 4076。
在 Pages/_ViewStart.cshtml 文件中設(shè)置 Layout 屬性:
CSHTML
@{
Layout = "_Layout";
}
前面的標(biāo)記針對所有 Razor 文件將布局文件設(shè)置為 Pages 文件夾下的 Pages/Shared/_Layout.cshtml。 請參閱布局了解詳細(xì)信息。
檢查 Pages/Movies/Create.cshtml.cs 頁面模型:
C#
// Unused usings removed.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesMovie.Models;
using System;
using System.Threading.Tasks;
namespace RazorPagesMovie.Pages.Movies
{
public class CreateModel : PageModel
{
private readonly RazorPagesMovie.Models.RazorPagesMovieContext _context;
public CreateModel(RazorPagesMovie.Models.RazorPagesMovieContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public Movie Movie { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
OnGet 方法初始化頁面所需的任何狀態(tài)。 “創(chuàng)建”頁沒有任何要初始化的狀態(tài),因此返回 Page。 教程的后面部分將介紹 OnGet 方法初始化狀態(tài)。 Page 方法創(chuàng)建用于呈現(xiàn) Create.cshtml 頁的 PageResult 對象。
Movie 屬性使用 [BindProperty] 特性來選擇加入模型綁定。 當(dāng)“創(chuàng)建”表單發(fā)布表單值時(shí),ASP.NET Core 運(yùn)行時(shí)將發(fā)布的值綁定到 Movie 模型。
當(dāng)頁面發(fā)布表單數(shù)據(jù)時(shí),運(yùn)行 OnPostAsync 方法:
C#
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Movie.Add(Movie);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
如果不存在任何模型錯(cuò)誤,將重新顯示表單,以及發(fā)布的任何表單數(shù)據(jù)。 在發(fā)布表單前,可以在客戶端捕獲到大部分模型錯(cuò)誤。 模型錯(cuò)誤的一個(gè)示例是,發(fā)布的日期字段值無法轉(zhuǎn)換為日期。 本教程后面討論了客戶端驗(yàn)證和模型驗(yàn)證。
如果不存在模型錯(cuò)誤,將保存數(shù)據(jù),并且瀏覽器會重定向到索引頁。
檢查 Pages/Movies/Create.cshtml Razor 頁面文件:
CSHTML
@page
@model RazorPagesMovie.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");}
}
Visual Studio 以用于標(biāo)記幫助程序的特殊加粗字體顯示 <form method="post">
標(biāo)記:
<form method="post"> 元素是一個(gè)表單標(biāo)記幫助程序。 表單標(biāo)記幫助程序會自動包含防偽令牌。
基架引擎在模型中為每個(gè)字段(ID 除外)創(chuàng)建 Razor 標(biāo)記,如下所示:
CSHTML
<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>
驗(yàn)證標(biāo)記幫助程序(<div asp-validation-summary 和 <span asp-validation-for)顯示驗(yàn)證錯(cuò)誤。 本系列后面的部分將更詳細(xì)地討論有關(guān)驗(yàn)證的信息。
標(biāo)簽標(biāo)記幫助程序 (<label asp-for="Movie.Title" class="control-label"></label>) 生成標(biāo)簽描述和 Title 屬性的 for 特性。
輸入標(biāo)記幫助程序 (<input asp-for="Movie.Title" class="form-control" />) 使用 DataAnnotations 屬性并在客戶端生成 jQuery 驗(yàn)證所需的 HTML 屬性。
更多建議: