Razor 頁面是 ASP.NET Core MVC 的一個(gè)新功能,它可以使基于頁面的編碼方式更簡單高效鸿捧。
若要查找使用模型視圖控制器方法的教程泻轰,請(qǐng)參閱 ASP.NET Core MVC 入門铺然。
本文檔介紹 Razor 頁面俗孝。 它并不是分步教程。 如果認(rèn)為某些部分過于復(fù)雜魄健,請(qǐng)參閱 Razor 頁面入門赋铝。 有關(guān) ASP.NET Core 的概述,請(qǐng)參閱 ASP.NET Core 簡介沽瘦。
系統(tǒng)必備
Install one of the following:
- CLI tooling: Windows, Linux, or macOS: .NET Core SDK 2.0 or later
- IDE/editor tooling
- Windows: Visual Studio for Windows
- ASP.NET and web development workload
- .NET Core cross-platform development workload
- Linux: Visual Studio Code
- macOS: Visual Studio for Mac
- Windows: Visual Studio for Windows
創(chuàng)建 Razor 頁面項(xiàng)目
Visual Studio
請(qǐng)參閱 Razor 頁面入門革骨,獲取關(guān)于如何使用 Visual Studio 創(chuàng)建 Razor 頁面項(xiàng)目的詳細(xì)說明农尖。
Visual Studio for Mac
在命令行中運(yùn)行dotnet new razor
。
在 Visual Studio for Mac 中打開生成的 .csproj 文件良哲。
Visual Studio Code
在命令行中運(yùn)行dotnet new razor
盛卡。
.NET Core CLI
在命令行中運(yùn)行dotnet new razor
。
Razor 頁面
Startup.cs 中已啟用 Razor 頁面:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Includes support for Razor Pages and controllers.
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
請(qǐng)考慮一個(gè)基本頁面:
@page
<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>
上述代碼看上去類似于一個(gè) Razor 視圖文件筑凫。 不同之處在于 @page
指令窟扑。 @page
使文件轉(zhuǎn)換為一個(gè) MVC 操作 ,這意味著它將直接處理請(qǐng)求漏健,而無需通過控制器處理。 @page
必須是頁面上的第一個(gè) Razor 指令橘霎。 @page
將影響其他 Razor 構(gòu)造的行為蔫浆。
將在以下兩個(gè)文件中顯示使用 PageModel
類的類似頁面。 Pages/Index2.cshtml 文件:
@page
@using RazorPagesIntro.Pages
@model IndexModel2
<h2>Separate page model</h2>
<p>
@Model.Message
</p>
Pages/Index2.cshtml.cs 頁面模型:
using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
namespace RazorPagesIntro.Pages
{
public class IndexModel2 : PageModel
{
public string Message { get; private set; } = "PageModel in C#";
public void OnGet()
{
Message += $" Server time is { DateTime.Now }";
}
}
}
按照慣例姐叁,PageModel
類文件的名稱與追加 .cs 的 Razor 頁面文件名稱相同瓦盛。 例如,前面的 Razor 頁面的名稱為 Pages/Index2.cshtml外潜。 包含 PageModel
類的文件的名稱為 Pages/Index2.cshtml.cs原环。
頁面的 URL 路徑的關(guān)聯(lián)由頁面在文件系統(tǒng)中的位置決定。 下表顯示了 Razor 頁面路徑及匹配的 URL:
文件名和路徑 | 匹配的 URL |
---|---|
/Pages/Index.cshtml |
/ 或 /Index
|
/Pages/Contact.cshtml | /Contact |
/Pages/Store/Contact.cshtml | /Store/Contact |
/Pages/Store/Index.cshtml |
/Store 或 /Store/Index
|
注意:
默認(rèn)情況下处窥,運(yùn)行時(shí)在“Pages”文件夾中查找 Razor 頁面文件嘱吗。
URL 未包含頁面時(shí),Index
為默認(rèn)頁面滔驾。
編寫基本窗體
Razor 頁面功能旨在簡化 Web 瀏覽器常用的模式谒麦。 模型綁定、標(biāo)記幫助程序和 HTML 幫助程序均只可用于 Razor 頁面類中定義的屬性哆致。 請(qǐng)參考為 Contact
模型實(shí)現(xiàn)基本的“聯(lián)系我們”窗體的頁面:
在本文檔中的示例中绕德,DbContext
在 Startup.cs 文件中進(jìn)行初始化。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesContacts.Data;
namespace RazorPagesContacts
{
public class Startup
{
public IHostingEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("name"));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
}
數(shù)據(jù)模型:
using System.ComponentModel.DataAnnotations;
namespace RazorPagesContacts.Data
{
public class Customer
{
public int Id { get; set; }
[Required, StringLength(100)]
public string Name { get; set; }
}
}
數(shù)據(jù)庫上下文:
using Microsoft.EntityFrameworkCore;
namespace RazorPagesContacts.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options)
: base(options)
{
}
public DbSet<Customer> Customers { get; set; }
}
}
Pages/Create.cshtml 視圖文件:
@page
@model RazorPagesContacts.Pages.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>
Pages/Create.cshtml.cs 頁面模型:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
namespace RazorPagesContacts.Pages
{
public class CreateModel : PageModel
{
private readonly AppDbContext _db;
public CreateModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
}
}
按照慣例摊阀,PageModel
類命名為 <PageName>Model
并且它與頁面位于同一個(gè)命名空間中耻蛇。
使用 PageModel
類,可以將頁面的邏輯與其展示分離開來胞此。 它定義了頁面處理程序臣咖,用于處理發(fā)送到頁面的請(qǐng)求和用于呈現(xiàn)頁面的數(shù)據(jù)。 借助這種分離豌鹤,可以通過依賴關(guān)系注入管理頁面依賴關(guān)系亡哄,并對(duì)頁面執(zhí)行單元測試。
頁面包含 OnPostAsync
處理程序方法布疙,它在 POST
請(qǐng)求上運(yùn)行(當(dāng)用戶發(fā)布窗體時(shí))蚊惯。 可以為任何 HTTP 謂詞添加處理程序方法愿卸。 最常見的處理程序是:
-
OnGet
,用于初始化頁面所需的狀態(tài)截型。 OnGet 示例趴荸。 -
OnPost
,用于處理窗體提交宦焦。
Async
命名后綴為可選发钝,但是按照慣例通常會(huì)將它用于異步函數(shù)。 前面示例中的 OnPostAsync
代碼看上去與通常在控制器中編寫的內(nèi)容相似波闹。 前面的代碼通常用于 Razor 頁面酝豪。 多數(shù) MVC 基元(例如模型綁定、驗(yàn)證和操作結(jié)果)都是共享的精堕。
之前的 OnPostAsync
方法:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
OnPostAsync
的基本流:
檢查驗(yàn)證錯(cuò)誤孵淘。
- 如果沒有錯(cuò)誤,則保存數(shù)據(jù)并重定向歹篓。
- 如果有錯(cuò)誤瘫证,則再次顯示頁面并附帶驗(yàn)證消息。 客戶端驗(yàn)證與傳統(tǒng)的 ASP.NET Core MVC 應(yīng)用程序相同庄撮。 很多情況下背捌,都會(huì)在客戶端上檢測到驗(yàn)證錯(cuò)誤,并且從不將它們提交到服務(wù)器洞斯。
成功輸入數(shù)據(jù)后毡庆,OnPostAsync
處理程序方法調(diào)用 RedirectToPage
幫助程序方法來返回 RedirectToPageResult
的實(shí)例。 RedirectToPage
是新的操作結(jié)果烙如,類似于 RedirectToAction
或 RedirectToRoute
扭仁,但是已針對(duì)頁面進(jìn)行自定義。 在前面的示例中厅翔,它將重定向到根索引頁 (/Index
)乖坠。 頁面 URL 生成部分中詳細(xì)介紹了 RedirectToPage
。
提交的窗體存在(已傳遞到服務(wù)器的)驗(yàn)證錯(cuò)誤時(shí)刀闷,OnPostAsync
處理程序方法調(diào)用 Page
幫助程序方法熊泵。Page
返回 PageResult
的實(shí)例。 返回 Page
的過程與控制器中的操作返回 View
的過程相似甸昏。PageResult
是處理程序方法的默認(rèn) 返回類型顽分。 返回 void
的處理程序方法將顯示頁面。
Customer
屬性使用 [BindProperty]
特性來選擇加入模型綁定施蜜。
public class CreateModel : PageModel
{
private readonly AppDbContext _db;
public CreateModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
}
默認(rèn)情況下卒蘸,Razor 頁面只綁定帶有非 GET 謂詞的屬性。 綁定屬性可以減少需要編寫的代碼量。 綁定通過使用相同的屬性顯示窗體字段 (<input asp-for="Customer.Name" />
) 來減少代碼缸沃,并接受輸入恰起。
備注
出于安全原因,必須選擇綁定 GET 請(qǐng)求數(shù)據(jù)以對(duì)模型屬性進(jìn)行分頁趾牧。 請(qǐng)?jiān)趯⒂脩糨斎胗成涞綄傩郧皩?duì)其進(jìn)行驗(yàn)證检盼。 當(dāng)構(gòu)建依賴查詢字符串或路由值的功能時(shí),選擇加入此行為非常有用翘单。
若要將屬性綁定在 GET 請(qǐng)求上吨枉,請(qǐng)將[BindProperty]
特性的SupportsGet
屬性設(shè)置為true
:[BindProperty(SupportsGet = true)]
主頁 (Index.cshtml):
@page
@model RazorPagesContacts.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Contacts</h1>
<form method="post">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Customers)
{
<tr>
<td>@contact.Id</td>
<td>@contact.Name</td>
<td>
<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>
<button type="submit" asp-page-handler="delete"
asp-route-id="@contact.Id">delete</button>
</td>
</tr>
}
</tbody>
</table>
<a asp-page="./Create">Create</a>
</form>
Index.cshtml.cs 隱藏文件:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace RazorPagesContacts.Pages
{
public class IndexModel : PageModel
{
private readonly AppDbContext _db;
public IndexModel(AppDbContext db)
{
_db = db;
}
public IList<Customer> Customers { get; private set; }
public async Task OnGetAsync()
{
Customers = await _db.Customers.AsNoTracking().ToListAsync();
}
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _db.Customers.FindAsync(id);
if (contact != null)
{
_db.Customers.Remove(contact);
await _db.SaveChangesAsync();
}
return RedirectToPage();
}
}
}
Index.cshtml 文件包含以下標(biāo)記來創(chuàng)建每個(gè)聯(lián)系人項(xiàng)的編輯鏈接:
<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>
定位點(diǎn)標(biāo)記幫助程序 使用 asp-route-{value}
屬性生成“編輯”頁面的鏈接。 此鏈接包含路由數(shù)據(jù)及聯(lián)系人 ID 哄芜。 例如 http://localhost:5000/Edit/1
貌亭。
Pages/Edit.cshtml 文件:
@page "{id:int}"
@model RazorPagesContacts.Pages.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
ViewData["Title"] = "Edit Customer";
}
<h1>Edit Customer - @Model.Customer.Id</h1>
<form method="post">
<div asp-validation-summary="All"></div>
<input asp-for="Customer.Id" type="hidden" />
<div>
<label asp-for="Customer.Name"></label>
<div>
<input asp-for="Customer.Name" />
<span asp-validation-for="Customer.Name" ></span>
</div>
</div>
<div>
<button type="submit">Save</button>
</div>
</form>
第一行包含 @page "{id:int}"
指令。 路由約束 "{id:int}"
告訴頁面接受包含 int
路由數(shù)據(jù)的頁面請(qǐng)求认臊。 如果頁面請(qǐng)求未包含可轉(zhuǎn)換為 int
的路由數(shù)據(jù)属提,則運(yùn)行時(shí)返回 HTTP 404(未找到)錯(cuò)誤。 若要使 ID 可選美尸,請(qǐng)將 ?
追加到路由約束:
@page "{id:int?}"
Pages/Edit.cshtml.cs 文件:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Data;
namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;
public EditModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnGetAsync(int id)
{
Customer = await _db.Customers.FindAsync(id);
if (Customer == null)
{
return RedirectToPage("/Index");
}
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Attach(Customer).State = EntityState.Modified;
try
{
await _db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw new Exception($"Customer {Customer.Id} not found!");
}
return RedirectToPage("/Index");
}
}
}
Index.cshtml 文件還包含用于為每個(gè)客戶聯(lián)系人創(chuàng)建刪除按鈕的標(biāo)記:
<button type="submit" asp-page-handler="delete"
asp-route-id="@contact.Id">delete</button>
刪除按鈕采用 HTML 呈現(xiàn),其 formaction
包括參數(shù):
asp-route-id
屬性指定的客戶聯(lián)系人 ID斟薇。
asp-page-handler
屬性指定的 handler
师坎。
下面是呈現(xiàn)的刪除按鈕的示例,其中客戶聯(lián)系人 ID 為 1
:
<button type="submit" formaction="/?id=1&handler=delete">delete</button>
選中按鈕時(shí)堪滨,向服務(wù)器發(fā)送窗體 POST
請(qǐng)求胯陋。 按照慣例,根據(jù)方案 OnPost[handler]Async
基于 handler
參數(shù)的值來選擇處理程序方法的名稱袱箱。
因?yàn)楸臼纠?handler
是 delete
遏乔,因此 OnPostDeleteAsync
處理程序方法用于處理 POST
請(qǐng)求。 如果 asp-page-handler
設(shè)置為不同值(如 remove
)发笔,則選擇名稱為 OnPostRemoveAsync
的頁面處理程序方法盟萨。
public async Task<IActionResult> OnPostDeleteAsync(int id)
{
var contact = await _db.Customers.FindAsync(id);
if (contact != null)
{
_db.Customers.Remove(contact);
await _db.SaveChangesAsync();
}
return RedirectToPage();
}
OnPostDeleteAsync
方法:
接受來自查詢字符串的 id
。
使用 FindAsync
查詢客戶聯(lián)系人的數(shù)據(jù)庫了讨。
如果找到客戶聯(lián)系人捻激,則從客戶聯(lián)系人列表將其刪除。 數(shù)據(jù)庫將更新前计。
調(diào)用 RedirectToPage
胞谭,重定向到根索引頁 (/Index
) 。
XSRF/CSRF 和 Razor 頁面
無需為防偽驗(yàn)證編寫任何代碼男杈。Razor 頁面自動(dòng)將防偽標(biāo)記生成過程和驗(yàn)證過程包含在內(nèi)丈屹。
將布局、分區(qū)伶棒、模板和標(biāo)記幫助程序用于 Razor 頁面
頁面可使用 Razor 視圖引擎的所有功能旺垒。 布局彩库、分區(qū)、模板袖牙、標(biāo)記幫助程序侧巨、 _ViewStart.cshtml 和 _ViewImports.cshtml 的工作方式與它們?cè)趥鹘y(tǒng)的 Razor 視圖中的工作方式相同。
我們來使用其中的一些功能來整理此頁面鞭达。
向 Pages/_Layout.cshtml 添加布局頁面:
<!DOCTYPE html>
<html>
<head>
<title>Razor Pages Sample</title>
</head>
<body>
<a asp-page="/Index">Home</a>
@RenderBody()
<a asp-page="/Customers/Create">Create</a> <br />
</body>
</html>
布局:
- 控制每個(gè)頁面的布局(頁面選擇退出布局時(shí)除外)司忱。
- 導(dǎo)入 HTML 結(jié)構(gòu),例如 JavaScript 和樣式表畴蹭。
請(qǐng)參閱布局頁面了解詳細(xì)信息坦仍。
在 Pages/_ViewStart.cshtml 中設(shè)置 Layout 屬性:
@{
Layout = "_Layout";
}
注意:布局位于“頁面”文件夾中。 頁面按層次結(jié)構(gòu)從當(dāng)前頁面的文件夾開始查找其他視圖(布局叨襟、模板繁扎、分區(qū))。 可以從“頁面”文件夾下的任意 Razor 頁面使用“頁面”文件夾中的布局糊闽。
建議不要將布局文件放在“視圖/共享”文件夾中梳玫。 視圖/共享 是一種 MVC 視圖模式。Razor 頁面旨在依賴文件夾層次結(jié)構(gòu)右犹,而非路徑約定提澎。
Razor 頁面中的視圖搜索包含“頁面”文件夾。 用于 MVC 控制器和傳統(tǒng) Razor 視圖的布局念链、模板和分區(qū)可直接工作盼忌。
添加 Pages/_ViewImports.cshtml 文件:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
本教程的后續(xù)部分中將介紹 @namespace
。 @addTagHelper
指令將內(nèi)置標(biāo)記幫助程序引入“頁面”文件夾中的所有頁面掂墓。
頁面上顯式使用 @namespace
指令后:
@page
@namespace RazorPagesIntro.Pages.Customers
@model NameSpaceModel
<h2>Name space</h2>
<p>
@Model.Message
</p>
此指令將為頁面設(shè)置命名空間谦纱。 @model
指令無需包含命名空間。
_ViewImports.cshtml 中包含 @namespace
指令后君编,指定的命名空間將為在導(dǎo)入 @namespace
指令的頁面中生成的命名空間提供前綴跨嘉。 生成的命名空間的剩余部分(后綴部分)是包含 _ViewImports.cshtml 的文件夾與包含頁面的文件夾之間以點(diǎn)分隔的相對(duì)路徑。
例如吃嘿,代碼隱藏文件 Pages/Customers/Edit.cshtml.cs 顯式設(shè)置命名空間:
namespace RazorPagesContacts.Pages
{
public class EditModel : PageModel
{
private readonly AppDbContext _db;
public EditModel(AppDbContext db)
{
_db = db;
}
// Code removed for brevity.
Pages/_ViewImports.cshtml 文件設(shè)置以下命名空間:
@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
為 Pages/Customers/Edit.cshtml Razor 頁面生成的命名空間與代碼隱藏文件相同. 已對(duì) @namespace
指令進(jìn)行設(shè)計(jì)偿荷,因此添加到項(xiàng)目的 C# 類和頁面生成的代碼可直接工作,而無需添加代碼隱藏文件的 @using
指令唠椭。
注意: @namespace
也可用于傳統(tǒng)的 Razor 視圖跳纳。
原始的 Pages/Create.cshtml 視圖文件:
@page
@model RazorPagesContacts.Pages.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>
更新后的 Pages/Create.cshtml 視圖文件:
@page
@model CreateModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" />
</form>
</body>
</html>
頁面的 URL 生成
之前顯示的 Create
頁面使用 RedirectToPage
:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
應(yīng)用具有以下文件/文件夾結(jié)構(gòu):
- /Pages
- Index.cshtml
- /Customer
- Create.cshtml
- Edit.cshtml
- Index.cshtml
成功后, Pages/Customers/Create.cshtml 和 Pages/Customers/Edit.cshtml 頁面將重定向到 Pages/Index.cshtml 贪嫂。字符串 /Index
是用于訪問上一頁的 URI 的組成部分寺庄。可以使用字符串 /Index
生成 Pages/Index.cshtml 頁面的 URI 。例如:
Url.Page("/Index", ...)
<a asp-page="/Index">My Index Page</a>
RedirectToPage("/Index")
頁面名稱是從根“/Pages”文件夾到頁面的路徑(包含前導(dǎo) /
斗塘,例如 /Index
)赢织。相較于僅對(duì) URL 硬編碼,前面的 URL 生成示例的功能更加強(qiáng)大馍盟。URL 生成使用路由于置,并且可以根據(jù)目標(biāo)路徑定義路由的方式生成參數(shù)并對(duì)參數(shù)編碼。
頁面的URL生成支持相對(duì)名稱贞岭。 下表顯示了 Pages/Customers/Create.cshtml 中不同的 RedirectToPage
參數(shù)選擇的索引頁:
RedirectToPage(x) | 頁 |
---|---|
RedirectToPage("/Index") | Pages/Index |
RedirectToPage("./Index") | Pages/Customers/Index |
RedirectToPage("../Index") | Pages/Index |
RedirectToPage("Index") | Pages/Customers/Index |
RedirectToPage("Index")
八毯、 RedirectToPage("./Index")
和 RedirectToPage("../Index")
是相對(duì)名稱。 結(jié)合 RedirectToPage
參數(shù)與當(dāng)前頁的路徑來計(jì)算目標(biāo)頁面的名稱瞄桨。
構(gòu)建結(jié)構(gòu)復(fù)雜的站點(diǎn)時(shí)话速,相對(duì)名稱鏈接很有用。 如果使用相對(duì)名稱鏈接文件夾中的頁面芯侥,則可以重命名該文件夾泊交。 所有鏈接仍然有效(因?yàn)檫@些鏈接未包含此文件夾名稱)。
TempData
ASP.NET在控制器上公開了 TempData 屬性柱查。 此屬性存儲(chǔ)未讀取的數(shù)據(jù)廓俭。 Keep
和 Peek
方法可用于檢查數(shù)據(jù),而不執(zhí)行刪除唉工。 多個(gè)請(qǐng)求需要數(shù)據(jù)時(shí)研乒, TempData
有助于進(jìn)行重定向。
[TempData]
是 ASP.NET Core 2.0 中的新屬性酵紫,在控制器和頁面上受支持。
下面的代碼使用 TempData
設(shè)置 Message
的值:
public class CreateDotModel : PageModel
{
private readonly AppDbContext _db;
public CreateDotModel(AppDbContext db)
{
_db = db;
}
[TempData]
public string Message { get; set; }
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
Message = $"Customer {Customer.Name} added";
return RedirectToPage("./Index");
}
}
Pages/Customers/Index.cshtml 文件中的以下標(biāo)記使用 TempData
顯示 Message
的值错维。
<h3>Msg: @Model.Message</h3>
Pages/Customers/Index.cshtml.cs頁面模型將[TempData]
屬性應(yīng)用到Message
屬性奖地。
[TempData]
public string Message { get; set; }
請(qǐng)參閱 TempData 了解詳細(xì)信息。
針對(duì)一個(gè)頁面的多個(gè)處理程序
以下頁面使用 asp-page-handler
標(biāo)記幫助程序?yàn)閮蓚€(gè)頁面處理程序生成標(biāo)記:
@page
@model CreateFATHModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>
前面示例中的窗體包含兩個(gè)提交按鈕赋焕,每個(gè)提交按鈕均使用 FormActionTagHelper
提交到不同的 URL 参歹。 asp-page-handler
是 asp-page
的配套屬性。 asp-page-handler
生成提交到頁面定義的各個(gè)處理程序方法的 URL 隆判。未指定 asp-page
犬庇,因?yàn)槭纠焰溄拥疆?dāng)前頁面。
頁面模型:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
namespace RazorPagesContacts.Pages.Customers
{
public class CreateFATHModel : PageModel
{
private readonly AppDbContext _db;
public CreateFATHModel(AppDbContext db)
{
_db = db;
}
[BindProperty]
public Customer Customer { get; set; }
public async Task<IActionResult> OnPostJoinListAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_db.Customers.Add(Customer);
await _db.SaveChangesAsync();
return RedirectToPage("/Index");
}
public async Task<IActionResult> OnPostJoinListUCAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
Customer.Name = Customer.Name?.ToUpper();
return await OnPostJoinListAsync();
}
}
}
前面的代碼使用已命名處理程序方法侨嘀。已命名處理程序方法通過采用名稱中 On<HTTP Verb>
之后及 Async
之前的文本(如果有)創(chuàng)建臭挽。 在前面的示例中,頁面方法是 OnPostJoinListAsync 和 OnPostJoinListUCAsync 咬腕。刪除 OnPost 和 Async 后欢峰,處理程序名稱為 JoinList
和 JoinListUC
。
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
使用前面的代碼時(shí),提交到 OnPostJoinListAsync
的 URL 路徑為 http://localhost:5000/Customers/CreateFATH?handler=JoinList
纽帖。提交到 OnPostJoinListUCAsync
的 URL 路徑為 http://localhost:5000/Customers/CreateFATH?handler=JoinListUC
宠漩。
自定義路由
如果你不喜歡 URL 中的查詢字符串 ?handler=JoinList
,可以更改路由懊直,將處理程序名稱放在 URL 的路徑部分扒吁。可以通過在 @page
指令后面添加使用雙引號(hào)括起來的路由模板來自定義路由室囊。
@page "{handler?}"
@model CreateRouteModel
<html>
<body>
<p>
Enter your name.
</p>
<div asp-validation-summary="All"></div>
<form method="POST">
<div>Name: <input asp-for="Customer.Name" /></div>
<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
</form>
</body>
</html>
前面的路由將處理程序放在了 URL 路徑中雕崩,而不是查詢字符串中。handler
前面的 ?
表示路由參數(shù)為可選波俄。
可以使用 @page
將其他段和參數(shù)添加到頁面的路由中晨逝。 其中的任何內(nèi)容均會(huì)被追加到頁面的默認(rèn)路由中。 不支持使用絕對(duì)路徑或虛擬路徑更改頁面的路由(如 "~/Some/Other/Path"
)懦铺。
配置和設(shè)置
若要配置高級(jí)選項(xiàng)捉貌,請(qǐng)?jiān)?MVC 生成器上使用 AddRazorPagesOptions
擴(kuò)展方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.RootDirectory = "/MyPages";
options.Conventions.AuthorizeFolder("/MyPages/Admin");
});
}
目前,可以使用 RazorPagesOptions
設(shè)置頁面的根目錄冬念,或者為頁面添加應(yīng)用程序模型約定趁窃。 通過這種方式,我們?cè)趯頃?huì)實(shí)現(xiàn)更多擴(kuò)展功能急前。
若要預(yù)編譯視圖醒陆,請(qǐng)參閱 Razor 視圖編譯。
請(qǐng)參閱 Razor 頁面入門裆针,這篇文章以本文為基礎(chǔ)編寫刨摩。
指定 Razor 頁面位于內(nèi)容根目錄中
默認(rèn)情況下,Razor 頁面位于 /Pages 目錄的根位置世吨。向 AddMvc 添加 WithRazorPagesAtContentRoot澡刹,以指定 Razor 頁面位于應(yīng)用的內(nèi)容根目錄 (ContentRootPath) 中:
services.AddMvc()
.AddRazorPagesOptions(options =>
{
...
})
.WithRazorPagesAtContentRoot();
指定 Razor 頁面位于自定義根目錄中
向 AddMvc 添加 WithRazorPagesRoot,以指定 Razor 頁面位于應(yīng)用中自定義根目錄位置(提供相對(duì)路徑):
services.AddMvc()
.AddRazorPagesOptions(options =>
{
...
})
.WithRazorPagesRoot("/path/to/razor/pages");