RazorASP.NET Core 中的頁面簡介Introduction to Razor Pages in ASP.NET Core

作者:Rick AndersonRyan NowakBy Rick Anderson and Ryan Nowak

Razor 頁面可讓撰寫以頁面為焦點的案常式序代碼比使用控制器和視圖更簡單且更具生產力。Razor Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

如果您在尋找使用模型檢視控制器方法的教學課程,請參閱開始使用 ASP.NET Core MVCIf you're looking for a tutorial that uses the Model-View-Controller approach, see Get started with ASP.NET Core MVC.

本檔提供 Razor 頁面簡介。This document provides an introduction to Razor Pages. 它不是逐步教學課程。It's not a step by step tutorial. 如果您發現某些區段太過先進,請參閱 開始使用 Razor 頁面If you find some of the sections too advanced, see Get started with Razor Pages. 如需 ASP.NET Core 的概觀,請參閱ASP.NET Core 簡介For an overview of ASP.NET Core, see the Introduction to ASP.NET Core.

必要條件Prerequisites

建立 Razor 頁面專案Create a Razor Pages project

如需如何建立頁面專案的詳細指示,請參閱 開始使用 Razor 頁面 Razor 。See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Razor 頁面Razor Pages

Razor 頁面已在 Startup.cs 中啟用:Razor Pages is enabled in Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

請考慮使用基本頁面:Consider a basic page:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

上述程式碼看起來很像是在具有控制器和 views 的 ASP.NET Core 應用程式中使用的 Razor 視圖檔案。The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. 這會讓它不同的是指示詞 @pageWhat makes it different is the @page directive. @page 會將檔案轉換成 MVC 動作,這表示它會直接處理要求,不用透過控制器。@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page 必須是頁面上的第一個指示詞 Razor 。@page must be the first Razor directive on a page. @page 會影響其他結構的行為 Razor@page affects the behavior of other Razor constructs. Razor 分頁檔名的名稱必須是 cshtml 尾碼。Razor Pages file names have a .cshtml suffix.

使用PageModel類別的類似頁面,顯示於下列兩個檔案中。A similar page, using a PageModel class, is shown in the following two files. Pages/Index2.cshtml 檔案:The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model Index2Model

<h2>Separate page model</h2>
<p>
    @Model.Message
</p>

Pages/Index2.cshtml.cs 頁面模型:The Pages/Index2.cshtml.cs page model:

using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;

namespace RazorPagesIntro.Pages
{
    public class Index2Model : PageModel
    {
        public string Message { get; private set; } = "PageModel in C#";

        public void OnGet()
        {
            Message += $" Server time is { DateTime.Now }";
        }
    }
}

依照慣例,類別檔案的名稱會與 PageModel Razor 附加 .cs 的分頁檔相同。By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. 例如,前一 Razor 頁是 Pages/index2.cshtml.cs。For example, the previous Razor Page is Pages/Index2.cshtml. 包含 PageModel 類別的檔案名為 Pages/Index2.cshtml.csThe file containing the PageModel class is named Pages/Index2.cshtml.cs.

頁面的 URL 路徑關聯是由頁面在檔案系統中的位置決定。The associations of URL paths to pages are determined by the page's location in the file system. 下表顯示 Razor 頁面路徑和相符的 URL:The following table shows a Razor Page path and the matching URL:

檔案名稱和路徑File name and path 比對 URLmatching URL
/Pages/Index.cshtml/Pages/Index.cshtml //Index/ or /Index
/Pages/Contact.cshtml/Pages/Contact.cshtml /Contact
/Pages/Store/Contact.cshtml/Pages/Store/Contact.cshtml /Store/Contact
/Pages/Store/Index.cshtml/Pages/Store/Index.cshtml /Store/Store/Index/Store or /Store/Index

注意:Notes:

  • 執行時間預設會 Razor 在 [ pages ] 資料夾中尋找分頁檔。The runtime looks for Razor Pages files in the Pages folder by default.
  • Index 是 URL 未包含頁面時的預設頁面。Index is the default page when a URL doesn't include a page.

撰寫基本表單Write a basic form

Razor 頁面的設計目的是要讓搭配網頁瀏覽器使用的常見模式在建立應用程式時很容易執行。Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. 模型系結 、卷標協助程式和 HTML 協助程式全都 使用頁面類別中定義的屬性 Razor 。Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Contact 模型請考慮實作基本的「與我們連絡」格式頁面:Consider a page that implements a basic "contact us" form for the Contact model:

本文件中的範例,會在 Startup.cs 檔案中初始化 DbContextFor the samples in this document, the DbContext is initialized in the Startup.cs file.

記憶體中的資料庫需要 Microsoft.EntityFrameworkCore.InMemory NuGet 套件。The in memory database requires the Microsoft.EntityFrameworkCore.InMemory NuGet package.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CustomerDbContext>(options =>
                      options.UseInMemoryDatabase("name"));
    services.AddRazorPages();
}

資料模型:The data model:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string Name { get; set; }
    }
}

DB 內容:The db context:

using Microsoft.EntityFrameworkCore;
using RazorPagesContacts.Models;

namespace RazorPagesContacts.Data
{
    public class CustomerDbContext : DbContext
    {
        public CustomerDbContext(DbContextOptions options)
            : base(options)
        {
        }

        public DbSet<Customer> Customers { get; set; }
    }
}

Pages/Create.cshtml 檢視檔案:The Pages/Create.cshtml view file:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

Pages/Create.cshtml.cs 頁面模型:The Pages/Create.cshtml.cs page model:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesContacts.Data;
using RazorPagesContacts.Models;
using System.Threading.Tasks;

namespace RazorPagesContacts.Pages.Customers
{
    public class CreateModel : PageModel
    {
        private readonly CustomerDbContext _context;

        public CreateModel(CustomerDbContext context)
        {
            _context = context;
        }

        public IActionResult OnGet()
        {
            return Page();
        }

        [BindProperty]
        public Customer Customer { get; set; }

        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            _context.Customers.Add(Customer);
            await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        }
    }
}

依照慣例,PageModel 類別稱之為 <PageName>Model,與頁面位於相同的命名空間。By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

PageModel 類別可以分離頁面邏輯與頁面展示。The PageModel class allows separation of the logic of a page from its presentation. 此類別會定義頁面的處理常式,以處理傳送至頁面的要求與用於轉譯頁面的資料。It defines page handlers for requests sent to the page and the data used to render the page. 這種分隔允許:This separation allows:

POST 要求上執行的頁面具有 「處理常式方法」OnPostAsync (當使用者張貼表單時)。The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). 可以新增任何 HTTP 指令動詞的處理常式方法。Handler methods for any HTTP verb can be added. 最常見的處理常式包括:The most common handlers are:

  • OnGet,初始化頁所需要的狀態。OnGet to initialize state needed for the page. 在上述程式碼中,此 OnGet 方法會顯示 CreateModel 的 cshtml Razor 頁面。In the preceding code, the OnGet method displays the CreateModel.cshtml Razor Page.
  • OnPost,處理表單提交作業。OnPost to handle form submissions.

Async 命名尾碼是選擇性的,但依照慣例通常用於非同步函式。The Async naming suffix is optional but is often used by convention for asynchronous functions. 上述程式碼一般適用于 Razor 頁面。The preceding code is typical for Razor Pages.

如果您熟悉使用控制器和 views 的 ASP.NET apps:If you're familiar with ASP.NET apps using controllers and views:

  • OnPostAsync上述範例中的程式碼看起來類似一般的控制器程式碼。The OnPostAsync code in the preceding example looks similar to typical controller code.
  • 大部分的 MVC 基本專案,例如 模型系結、 驗證和動作結果,其運作方式與控制器和 Razor 頁面相同。Most of the MVC primitives like model binding, validation, and action results work the same with Controllers and Razor Pages.

前一個 OnPostAsync 方法:The previous OnPostAsync method:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _context.Customers.Add(Customer);
    await _context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

OnPostAsync 的基本流程:The basic flow of OnPostAsync:

檢查驗證錯誤。Check for validation errors.

  • 如果沒有任何錯誤,會儲存資料並重新導向。If there are no errors, save the data and redirect.
  • 如果有錯誤,會再次顯示有驗證訊息的頁面。If there are errors, show the page again with validation messages. 在許多情況下,會在用戶端上偵測到驗證錯誤,且永遠不會提交到伺服器。In many cases, validation errors would be detected on the client, and never submitted to the server.

Pages/Create.cshtml 檢視檔案:The Pages/Create.cshtml view file:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

Pages/Create. cshtml 轉譯的 HTML:The rendered HTML from Pages/Create.cshtml:

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input type="text" data-val="true"
           data-val-length="The field Name must be a string with a maximum length of 10."
           data-val-length-max="10" data-val-required="The Name field is required."
           id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
    <input type="submit" />
    <input name="__RequestVerificationToken" type="hidden"
           value="<Antiforgery token here>" />
</form>

在先前的程式碼中,張貼表單:In the previous code, posting the form:

  • 包含有效資料:With valid data:

    • OnPostAsync處理常式方法會呼叫 RedirectToPage helper 方法。The OnPostAsync handler method calls the RedirectToPage helper method. RedirectToPage 會傳回 RedirectToPageResult 的執行個體。RedirectToPage returns an instance of RedirectToPageResult. RedirectToPage:RedirectToPage:

      • 是動作結果。Is an action result.
      • 類似于 RedirectToActionRedirectToRoute (用於控制器和 views) 。Is similar to RedirectToAction or RedirectToRoute (used in controllers and views).
      • 已針對頁面自訂。Is customized for pages. 在上述範例中,它會重新導向至根索引頁面 (/Index)。In the preceding sample, it redirects to the root Index page (/Index). 產生頁面 URL一節會詳細說明 RedirectToPageRedirectToPage is detailed in the URL generation for Pages section.
  • 傳遞至伺服器的驗證錯誤:With validation errors that are passed to the server:

    • OnPostAsync處理常式方法會呼叫 Page helper 方法。The OnPostAsync handler method calls the Page helper method. Page 會傳回 PageResult 的執行個體。Page returns an instance of PageResult. 傳回 Page 類似於控制站中的動作傳回 ViewReturning Page is similar to how actions in controllers return View. PageResult 這是處理常式方法的預設傳回型別。PageResult is the default return type for a handler method. 傳回 void 的處理常式方法會呈現頁面。A handler method that returns void renders the page.
    • 在上述範例中,不使用任何值張貼表單會導致 ModelState 傳回 false。In the preceding example, posting the form with no value results in ModelState.IsValid returning false. 在此範例中,用戶端上不會顯示任何驗證錯誤。In this sample, no validation errors are displayed on the client. 本檔稍後會討論驗證錯誤處理。Validation error handing is covered later in this document.
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
    
        _context.Customers.Add(Customer);
        await _context.SaveChangesAsync();
    
        return RedirectToPage("./Index");
    }
    
  • 使用用戶端驗證偵測到驗證錯誤:With validation errors detected by client side validation:

    • 資料 會張貼至伺服器。Data is not posted to the server.
    • 本檔稍後會說明用戶端驗證。Client-side validation is explained later in this document.

Customer屬性使用 [BindProperty] 屬性來加入宣告模型系結:The Customer property uses [BindProperty] attribute to opt in to model binding:

public class CreateModel : PageModel
{
    private readonly CustomerDbContext _context;

    public CreateModel(CustomerDbContext context)
    {
        _context = context;
    }

    public IActionResult OnGet()
    {
        return Page();
    }

    [BindProperty]
    public Customer Customer { get; set; }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Customers.Add(Customer);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

[BindProperty] 應該用於包含不應由用戶端變更之屬性的模型。[BindProperty] should not be used on models containing properties that should not be changed by the client. 如需詳細資訊,請參閱 大量指派For more information, see Overposting.

Razor 依預設,頁面只會系結具有非動詞命令的屬性 GETRazor Pages, by default, bind properties only with non-GET verbs. 系結至屬性不需要撰寫程式碼,就能將 HTTP 資料轉換成模型類型。Binding to properties removes the need to writing code to convert HTTP data to the model type. 透過使用相同的屬性呈現表單欄位 (<input asp-for="Customer.Name">) 並接受輸入,繫結可以減少程式碼。Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

警告

基於安全性考量,您必須選擇將 GET 要求資料繫結到頁面模型屬性。For security reasons, you must opt in to binding GET request data to page model properties. 請先驗證使用者輸入再將其對應至屬性。Verify user input before mapping it to properties. 在處理依賴於GET查詢字串或路由值的方案時,選擇綁定非常有用。Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

要對要求GET結合屬性,請將[BindProperty]屬性的SupportsGet屬性true設定為 :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

有關詳細資訊,請參閱ASP.NET核心社區站立:綁定 GET 討論 (YouTube)For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

檢查 Pages/Create. cshtml view 檔案:Reviewing the Pages/Create.cshtml view file:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>
  • 在上述程式碼中, 輸入標記協助程式會將 <input asp-for="Customer.Name" /> HTML 元素系結 <input>Customer.Name 模型運算式。In the preceding code, the input tag helper <input asp-for="Customer.Name" /> binds the HTML <input> element to the Customer.Name model expression.
  • @addTagHelper 讓標籤協助程式可供使用。@addTagHelper makes Tag Helpers available.

首頁The home page

Index. cshtml 是首頁:Index.cshtml is the home page:

@page
@model RazorPagesContacts.Pages.Customers.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h1>Contacts home page</h1>
<form method="post">
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in Model.Customer)
            {
                <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 New</a>
</form>

已建立關聯的 PageModel 類別 (Index.cshtml.cs):The associated PageModel class (Index.cshtml.cs):

public class IndexModel : PageModel
{
    private readonly CustomerDbContext _context;

    public IndexModel(CustomerDbContext context)
    {
        _context = context;
    }

    public IList<Customer> Customer { get; set; }

    public async Task OnGetAsync()
    {
        Customer = await _context.Customers.ToListAsync();
    }

    public async Task<IActionResult> OnPostDeleteAsync(int id)
    {
        var contact = await _context.Customers.FindAsync(id);

        if (contact != null)
        {
            _context.Customers.Remove(contact);
            await _context.SaveChangesAsync();
        }

        return RedirectToPage();
    }
}

索引的 cshtml 檔案包含下列標記:The Index.cshtml file contains the following markup:

<td>

<a /a>錨點標籤協助程式使用 asp-route-{value} 屬性來產生編輯頁面的連結。The <a /a> Anchor Tag Helper used the asp-route-{value} attribute to generate a link to the Edit page. 該連結包含路由資料和連絡人識別碼。The link contains route data with the contact ID. 例如: https://localhost:5001/Edit/1For example, https://localhost:5001/Edit/1. 標記 協助程式可讓伺服器端程式碼參與建立和轉譯檔案中的 HTML 元素 Razor 。Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.

索引的 cshtml 檔案包含標記,以建立每個客戶連絡人的 [刪除] 按鈕:The Index.cshtml file contains markup to create a delete button for each customer contact:

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
<button type="submit" asp-page-handler="delete"

呈現的 HTML:The rendered HTML:

<button type="submit" formaction="/Customers?id=1&amp;handler=delete">delete</button>

在 HTML 中轉譯 [刪除] 按鈕時,其 formaction 包含下列參數:When the delete button is rendered in HTML, its formaction includes parameters for:

  • 由屬性指定的客戶連絡人識別碼 asp-route-idThe customer contact ID, specified by the asp-route-id attribute.
  • handler屬性所指定的 asp-page-handlerThe handler, specified by the asp-page-handler attribute.

選取按鈕時,表單 POST 要求會傳送至伺服器。When the button is selected, a form POST request is sent to the server. 依照慣例,會依據配置 OnPost[handler]Async,按 handler 參數的值來選取處理常式方法。By convention, the name of the handler method is selected based on the value of the handler parameter according to the scheme OnPost[handler]Async.

在此範例中,因為 handlerdelete,所以會使用 OnPostDeleteAsync 處理常式方法來處理 POST 要求。Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. asp-page-handler 設為其他值 (例如 remove),則會選取名為 OnPostRemoveAsync 的處理常式方法。If the asp-page-handler is set to a different value, such as remove, a handler method with the name OnPostRemoveAsync is selected.

public async Task<IActionResult> OnPostDeleteAsync(int id)
{
    var contact = await _context.Customers.FindAsync(id);

    if (contact != null)
    {
        _context.Customers.Remove(contact);
        await _context.SaveChangesAsync();
    }

    return RedirectToPage();
}

OnPostDeleteAsync 方法:The OnPostDeleteAsync method:

  • id從查詢字串取得。Gets the id from the query string.
  • 使用 FindAsync 在資料庫中查詢客戶連絡人。Queries the database for the customer contact with FindAsync.
  • 如果找到客戶連絡人,則會將它移除,並更新資料庫。If the customer contact is found, it's removed and the database is updated.
  • 呼叫 RedirectToPage 以重新導向至根索引頁 (/Index)。Calls RedirectToPage to redirect to the root Index page (/Index).

編輯 cshtml 檔案The Edit.cshtml file

@page "{id:int}"
@model RazorPagesContacts.Pages.Customers.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers


<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}" 指示詞。The first line contains the @page "{id:int}" directive. 路由條件約束 "{id:int}" 通知頁面接受包含 int 路由資料的頁面要求。The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. 如果頁面要求不包含可以轉換成 int 的路由資料,執行階段會傳回 HTTP 404 (找不到) 錯誤。If a request to the page doesn't contain route data that can be converted to an int, the runtime returns an HTTP 404 (not found) error. 若要使識別碼成為選擇性,請將 ? 附加至路由條件約束:To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

Edit.cshtml.cs 檔案:The Edit.cshtml.cs file:

public class EditModel : PageModel
{
    private readonly CustomerDbContext _context;

    public EditModel(CustomerDbContext context)
    {
        _context = context;
    }

    [BindProperty]
    public Customer Customer { get; set; }

    public async Task<IActionResult> OnGetAsync(int id)
    {
        Customer = await _context.Customers.FindAsync(id);

        if (Customer == null)
        {
            return RedirectToPage("./Index");
        }

        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Attach(Customer).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            throw new Exception($"Customer {Customer.Id} not found!");
        }

        return RedirectToPage("./Index");
    }

}

驗證Validation

驗證規則:Validation rules:

  • 在模型類別中會以宣告方式指定。Are declaratively specified in the model class.
  • 會在應用程式的任何位置強制執行。Are enforced everywhere in the app.

System.ComponentModel.DataAnnotations命名空間會提供一組內建的驗證屬性,這些屬性會以宣告方式套用至類別或屬性。The System.ComponentModel.DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. DataAnnotations 也包含格式化屬性 [DataType] ,例如格式化的說明,而且不提供任何驗證。DataAnnotations also contains formatting attributes like [DataType] that help with formatting and don't provide any validation.

請考慮 Customer 模型:Consider the Customer model:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Models
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(10)]
        public string Name { get; set; }
    }
}

使用下列 Create. cshtml view 檔案:Using the following Create.cshtml view file:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Validation: customer name:</p>

<form method="post">
    <div asp-validation-summary="ModelOnly"></div>
    <span asp-validation-for="Customer.Name"></span>
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

上述程式碼:The preceding code:

  • 包含 jQuery 和 jQuery 驗證腳本。Includes jQuery and jQuery validation scripts.

  • 使用 <div /><span /> 標記 協助程式來啟用:Uses the <div /> and <span /> Tag Helpers to enable:

    • 用戶端驗證。Client-side validation.
    • 轉譯時發生驗證錯誤。Validation error rendering.
  • 產生下列 HTML:Generates the following HTML:

    <p>Enter a customer name:</p>
    
    <form method="post">
        Name:
        <input type="text" data-val="true"
               data-val-length="The field Name must be a string with a maximum length of 10."
               data-val-length-max="10" data-val-required="The Name field is required."
               id="Customer_Name" maxlength="10" name="Customer.Name" value="" />
        <input type="submit" />
        <input name="__RequestVerificationToken" type="hidden"
               value="<Antiforgery token here>" />
    </form>
    
    <script src="/lib/jquery/dist/jquery.js"></script>
    <script src="/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
    

張貼沒有名稱值的建立表單時,會顯示錯誤訊息:「需要名稱欄位」。Posting the Create form without a name value displays the error message "The Name field is required." 在表單上。on the form. 如果在用戶端上啟用 JavaScript,則瀏覽器會顯示錯誤,而不會張貼至伺服器。If JavaScript is enabled on the client, the browser displays the error without posting to the server.

[StringLength(10)]屬性會 data-val-length-max="10" 在呈現的 HTML 上產生。The [StringLength(10)] attribute generates data-val-length-max="10" on the rendered HTML. data-val-length-max 防止瀏覽器輸入超過指定的最大長度。data-val-length-max prevents browsers from entering more than the maximum length specified. 如果使用 Fiddler 之類的工具來編輯和重新播放 post:If a tool such as Fiddler is used to edit and replay the post:

  • 名稱超過10。With the name longer than 10.
  • 錯誤訊息「功能變數名稱必須是最大長度為10的字串」。The error message "The field Name must be a string with a maximum length of 10." 」錯誤訊息。is returned.

請考慮下列 Movie 模型:Consider the following Movie model:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string Rating { get; set; }
    }

驗證屬性會指定在其套用的模型屬性上強制執行的行為:The validation attributes specify behavior to enforce on the model properties they're applied to:

  • RequiredMinimumLength 屬性工作表示屬性必須有值,但不會防止使用者輸入空白字元來滿足這種驗證。The Required and MinimumLength attributes indicate that a property must have a value, but nothing prevents a user from entering white space to satisfy this validation.

  • RegularExpression 屬性則用來限制可輸入的字元。The RegularExpression attribute is used to limit what characters can be input. 在上述程式碼中,"Genre":In the preceding code, "Genre":

    • 必須指使用字母。Must only use letters.
    • 第一個字母必須是大寫。The first letter is required to be uppercase. 不允許使用空格、數字和特殊字元。White space, numbers, and special characters are not allowed.
  • RegularExpression "Rating":The RegularExpression "Rating":

    • 第一個字元必須為大寫字母。Requires that the first character be an uppercase letter.
    • 允許後續空格中的特殊字元和數位。Allows special characters and numbers in subsequent spaces. "PG-13" 對分級而言有效,但不適用於 "Genre"。"PG-13" is valid for a rating, but fails for a "Genre".
  • Range 屬性會將值限制在指定的範圍內。The Range attribute constrains a value to within a specified range.

  • StringLength屬性會設定字串屬性的最大長度,並選擇性地設定其最小長度。The StringLength attribute sets the maximum length of a string property, and optionally its minimum length.

  • 實值型別 (如decimalintfloatDateTime) 原本就是必要項目,而且不需要 [Required] 屬性。Value types (such as decimal, int, float, DateTime) are inherently required and don't need the [Required] attribute.

模型的 [建立] 頁面會顯示 Movie 具有無效值的錯誤:The Create page for the Movie model shows displays errors with invalid values:

有多個 jQuery 用戶端驗證錯誤的電影檢視表單

如需詳細資訊,請參閱For more information, see:

使用 OnGet 處理常式後援來處理 HEAD 要求Handle HEAD requests with an OnGet handler fallback

HEAD 要求可讓您取得特定資源的標頭。HEAD requests allow retrieving the headers for a specific resource. 不同於 GET 要求,HEAD 要求不會傳回回應主體。Unlike GET requests, HEAD requests don't return a response body.

一般來說,會為 HEAD 要求建立及呼叫 OnHead 處理常式:Ordinarily, an OnHead handler is created and called for HEAD requests:

public void OnHead()
{
    HttpContext.Response.Headers.Add("Head Test", "Handled by OnHead!");
}

RazorOnGet如果未 OnHead 定義任何處理程式,則頁面會切換回呼叫處理常式。Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined.

XSRF/CSRF 和 Razor PagesXSRF/CSRF and Razor Pages

Razor 頁面會受到 Antiforgery 驗證的保護。Razor Pages are protected by Antiforgery validation. FormTagHelper會將 antiforgery token 插入至 HTML 表單元素。The FormTagHelper injects antiforgery tokens into HTML form elements.

使用頁面的版面配置、部分、範本和標記協助程式 RazorUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

頁面會使用 view engine 的所有功能 Razor 。Pages work with all the capabilities of the Razor view engine. 配置、部分、範本、標籤協助程式、 _ViewStart cshtml_ViewImports. cshtml 的運作方式與傳統視圖的運作方式相同。 RazorLayouts, partials, templates, Tag Helpers, _ViewStart.cshtml, and _ViewImports.cshtml work in the same way they do for conventional Razor views.

可利用這些功能的一部分來整理這個頁面。Let's declutter this page by taking advantage of some of those capabilities.

版面配置頁面新增至 Pages/Shared/_Layout.cshtmlAdd a layout page to Pages/Shared/_Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
    <title>RP Sample</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
    <a asp-page="/Index">Home</a>
    <a asp-page="/Customers/Create">Create</a>
    <a asp-page="/Customers/Index">Customers</a> <br />

    @RenderBody()
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</body>
</html>

版面配置:The Layout:

  • 控制每個頁面的版面配置 (除非頁面退出版面配置)。Controls the layout of each page (unless the page opts out of layout).
  • 匯入 HTML 結構,例如 JavaScript 和樣式表。Imports HTML structures such as JavaScript and stylesheets.
  • 頁面的內容 Razor 會轉譯 @RenderBody() 為呼叫的位置。The contents of the Razor page are rendered where @RenderBody() is called.

如需詳細資訊,請參閱 版面配置頁面For more information, see layout page.

版面配置屬性是在 Pages/_ViewStart.cshtml 中設定:The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

版面配置位於 Pages/Shared 資料夾。The layout is in the Pages/Shared folder. 頁面會以階層方式尋找其他檢視 (版面配置、範本、部分),從目前頁面的相同資料夾開始。Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. 頁面/共用 資料夾中的版面配置可以從 Razor [ pages ] 資料夾下的任何頁面使用。A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

版面配置頁面應位於 Pages/Shared 資料夾中。The layout file should go in the Pages/Shared folder.

我們 建議您將配置檔案放入 Views/Shared 資料夾。We recommend you not put the layout file in the Views/Shared folder. Views/Shared 是 MVC 檢視模式。Views/Shared is an MVC views pattern. Razor 頁面的目的是要依賴資料夾階層,不是路徑慣例。Razor Pages are meant to rely on folder hierarchy, not path conventions.

頁面上的視圖搜尋 Razor 包含 Pages 資料夾。View search from a Razor Page includes the Pages folder. 適用于 MVC 控制器和傳統視圖的版面配置、範本和 Razor 部分 只會運作The layouts, templates, and partials used with MVC controllers and conventional Razor views just work.

新增 Pages/_ViewImports.cshtml 檔案:Add a Pages/_ViewImports.cshtml file:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

本教學課程稍後會說明 @namespace@namespace is explained later in the tutorial. @addTagHelper 指示詞會將 內建標記協助程式帶入 Pages 資料夾中的所有頁面。The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

@namespace 頁面上設定的指示詞:The @namespace directive set on a page:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
    @Model.Message
</p>

指示詞會 @namespace 設定頁面的命名空間。The @namespace directive sets the namespace for the page. @model 指示詞不需要包含命名空間。The @model directive doesn't need to include the namespace.

@namespace 指示詞包含在 _ViewImports.cshtml 中時,指定的命名空間會在匯入 @namespace 指示詞的頁面中提供所產生之命名空間的前置詞。When the @namespace directive is contained in _ViewImports.cshtml, the specified namespace supplies the prefix for the generated namespace in the Page that imports the @namespace directive. 所產生命名空間的其餘部分 (後置字元部分) 是包含 _ViewImports.cshtml 的資料夾和包含頁面的資料夾之間,以句點分隔的相對路徑。The rest of the generated namespace (the suffix portion) is the dot-separated relative path between the folder containing _ViewImports.cshtml and the folder containing the page.

例如,PageModel 類別 Pages/Customers/Edit.cshtml.cs 會明確地設定命名空間:For example, the PageModel class Pages/Customers/Edit.cshtml.cs explicitly sets the namespace:

namespace RazorPagesContacts.Pages
{
    public class EditModel : PageModel
    {
        private readonly AppDbContext _db;

        public EditModel(AppDbContext db)
        {
            _db = db;
        }

        // Code removed for brevity.

Pages/_ViewImports.cshtml 檔案會設定下列命名空間:The Pages/_ViewImports.cshtml file sets the following namespace:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

針對 Pages/Customers/Edit. cshtml 頁面產生的命名空間與 Razor PageModel 類別相同。The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace也可搭配傳統 Razor 視圖使用。@namespace also works with conventional Razor views.

請考慮 Pages/Create. cshtml view 檔案:Consider the Pages/Create.cshtml view file:

@page
@model RazorPagesContacts.Pages.Customers.CreateModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<p>Validation: customer name:</p>

<form method="post">
    <div asp-validation-summary="ModelOnly"></div>
    <span asp-validation-for="Customer.Name"></span>
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>

更新的 Pages/Create. cshtml view 檔案,其中包含 _ViewImports. cshtml 和先前的版面配置檔案:The updated Pages/Create.cshtml view file with _ViewImports.cshtml and the preceding layout file:

@page
@model CreateModel

<p>Enter a customer name:</p>

<form method="post">
    Name:
    <input asp-for="Customer.Name" />
    <input type="submit" />
</form>

在上述程式碼中, _ViewImports 的 cshtml 已匯入命名空間和標記協助程式。In the preceding code, the _ViewImports.cshtml imported the namespace and Tag Helpers. 設定檔案匯入 JavaScript 檔案。The layout file imported the JavaScript files.

Razor Pages 入門專案包含 pages/_ValidationScriptsPartial. cshtml,可連結用戶端驗證。The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

如需部分檢視的詳細資訊,請參閱 ASP.NET Core 中的部分檢視For more information on partial views, see ASP.NET Core 中的部分檢視.

產生頁面 URLURL generation for Pages

前面出現過的 Create 頁面使用 RedirectToPageThe Create page, shown previously, uses RedirectToPage:

public class CreateModel : PageModel
{
    private readonly CustomerDbContext _context;

    public CreateModel(CustomerDbContext context)
    {
        _context = context;
    }

    public IActionResult OnGet()
    {
        return Page();
    }

    [BindProperty]
    public Customer Customer { get; set; }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Customers.Add(Customer);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
}

應用程式有下列檔案/資料夾結構:The app has the following file/folder structure:

  • /Pages/Pages

    • Index.cshtmlIndex.cshtml

    • 隱私權. cshtmlPrivacy.cshtml

    • /Customers/Customers

      • Create.cshtmlCreate.cshtml
      • Edit.cshtmlEdit.cshtml
      • Index.cshtmlIndex.cshtml

Pages/customers/Create. cshtmlPages/customers/Edit. cshtml 頁面會在成功之後重新導向至 Pages/customers/Index。 cshtmlThe Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Customers/Index.cshtml after success. 字串 ./Index 是用來存取前一個頁面的相對頁面名稱。The string ./Index is a relative page name used to access the preceding page. 它是用來產生 Pages/Customers/Index. cshtml 頁面的 url。It is used to generate URLs to the Pages/Customers/Index.cshtml page. 例如:For example:

  • Url.Page("./Index", ...)
  • <a asp-page="./Index">Customers Index Page</a>
  • RedirectToPage("./Index")

絕對頁面名稱 /Index 是用來產生 Pages/Index. cshtml 頁面的 url。The absolute page name /Index is used to generate URLs to the Pages/Index.cshtml page. 例如:For example:

  • Url.Page("/Index", ...)
  • <a asp-page="/Index">Home Index Page</a>
  • RedirectToPage("/Index")

頁面名稱是從根 /Pages 資料夾到該頁面的路徑 (包括前置的 /,例如 /Index)。The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). 上述的 URL 產生範例提供增強的選項和功能功能,而不是硬式編碼 URL。The preceding URL generation samples offer enhanced options and functional capabilities over hard-coding a URL. URL 產生使用路由,可以根據路由在目的地路徑中定義的方式,產生並且編碼參數。URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

產生頁面 URL 支援相關的名稱。URL generation for pages supports relative names. 下表顯示使用 RedirectToPage Pages/Customers/Create. cshtml 中的不同參數所選取的索引頁面。The following table shows which Index page is selected using different RedirectToPage parameters in Pages/Customers/Create.cshtml.

RedirectToPage(x)RedirectToPage(x) 頁面Page
RedirectToPage("/Index")RedirectToPage("/Index") Pages/IndexPages/Index
RedirectToPage("./Index");RedirectToPage("./Index"); Pages/Customers/IndexPages/Customers/Index
RedirectToPage("../Index")RedirectToPage("../Index") Pages/IndexPages/Index
RedirectToPage("Index")RedirectToPage("Index") Pages/Customers/IndexPages/Customers/Index

RedirectToPage("Index")RedirectToPage("./Index")RedirectToPage("../Index")相對名稱RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. RedirectToPage 參數「結合」了目前頁面的路徑,以計算目的地頁面的名稱。The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

相對名稱連結在以複雜結構建置網站時很有用。Relative name linking is useful when building sites with a complex structure. 當使用相對名稱連結資料夾中的頁面時:When relative names are used to link between pages in a folder:

  • 重新命名資料夾並不會中斷相對連結。Renaming a folder doesn't break the relative links.
  • 連結不會中斷,因為它們不包含資料夾名稱。Links are not broken because they don't include the folder name.

若要重新導向到不同區域中的頁面,請指定區域:To redirect to a page in a different Area, specify the area:

RedirectToPage("/Index", new { area = "Services" });

如需詳細資訊,請參閱 ASP.NET Core 中的區域Razor ASP.NET Core 中的頁面路由和應用程式慣例For more information, see ASP.NET Core 中的區域 and Razor ASP.NET Core 中的頁面路由和應用程式慣例.

ViewData 屬性ViewData attribute

您可以使用將資料傳遞至頁面 ViewDataAttributeData can be passed to a page with ViewDataAttribute. 具有屬性的屬性(property) [ViewData] 會從儲存和載入其值 ViewDataDictionaryProperties with the [ViewData] attribute have their values stored and loaded from the ViewDataDictionary.

在下列範例中,會將 AboutModel [ViewData] 屬性套用至 Title 屬性:In the following example, the AboutModel applies the [ViewData] attribute to the Title property:

public class AboutModel : PageModel
{
    [ViewData]
    public string Title { get; } = "About";

    public void OnGet()
    {
    }
}

在 [關於] 頁面上,存取 Title 屬性作為模型屬性:In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

在此配置中,標題會從 ViewData 字典中讀取:In the layout, the title is read from the ViewData dictionary:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

TempDataTempData

ASP.NET Core 會公開 TempDataASP.NET Core exposes the TempData. 這個屬性會儲存資料,直到讀取為止。This property stores data until it's read. KeepPeek 方法可以用來檢查資料,不用刪除。The Keep and Peek methods can be used to examine the data without deletion. TempData 當需要多個單一要求的資料時,適用于重新導向。TempData is useful for redirection, when data is needed for more than a single request.

下列程式碼會設定使用 TempDataMessage 值:The following code sets the value of Message using TempData:

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 檔案中的下列標記會顯示使用 TempDataMessage 值。The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

<h3>Msg: @Model.Message</h3>

Pages/Customers/Index.cshtml.cs 頁面模型會將 [TempData] 屬性 (attribute) 套用到 Message 屬性 (property)。The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

[TempData]
public string Message { get; set; }

如需詳細資訊,請參閱 TempDataFor more information, see TempData.

每頁面有多個處理常式Multiple handlers per page

下列頁面會使用 asp-page-handler 標記協助程式為兩個處理常式產生標記:The following page generates markup for two handlers using the asp-page-handler Tag Helper:

@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>

上例中的表單有兩個提交按鈕,每一個都使用 FormActionTagHelper 提交至不同的 URL。The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. asp-page-handler 屬性附隨於 asp-pageThe asp-page-handler attribute is a companion to asp-page. asp-page-handler 產生的 URL 會提交至頁面所定義的每一個處理常式方法。asp-page-handler generates URLs that submit to each of the handler methods defined by a page. 因為範例連結至目前的頁面,所以未指定 asp-pageasp-page isn't specified because the sample is linking to the current page.

頁面模型:The page model:

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?.ToUpperInvariant();
            return await OnPostJoinListAsync();
        }
    }
}

上述程式碼使用「具名的處理常式方法」。The preceding code uses named handler methods. 具名的處理常式方法的建立方式是採用名稱中在 On<HTTP Verb> 後面、Async 之前 (如有) 的文字。Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). 在上例中,頁面方法是 OnPost JoinList Async 和 OnPost JoinListUC Async。In the preceding example, the page methods are OnPost JoinList Async and OnPost JoinListUC Async. 移除 OnPostAsync,處理常式名稱就是 JoinListJoinListUCWith OnPost and Async removed, the handler names are JoinList and JoinListUC.

<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

使用上述程式碼,提交至 OnPostJoinListAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH?handler=JoinListUsing the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinList. 提交至 OnPostJoinListUCAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH?handler=JoinListUCThe URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

自訂路由Custom routes

使用 @page 指示詞,可以:Use the @page directive to:

  • 指定頁面的自訂路由。Specify a custom route to a page. 例如,[關於] 頁面的路由可使用 @page "/Some/Other/Path" 設為 /Some/Other/PathFor example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • 將區段附加到頁面的預設路由。Append segments to a page's default route. 例如,使用 @page "item" 可將 "item" 區段新增到頁面的預設路由。For example, an "item" segment can be added to a page's default route with @page "item".
  • 將參數附加到頁面的預設路由。Append parameters to a page's default route. 例如,具有 @page "{id}" 的頁面可要求識別碼參數 idFor example, an ID parameter, id, can be required for a page with @page "{id}".

支援在路徑開頭以波狀符號 (~) 指定根相對路徑。A root-relative path designated by a tilde (~) at the beginning of the path is supported. 例如,@page "~/Some/Other/Path"@page "/Some/Other/Path" 相同。For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

如果您不喜歡 URL 中的查詢字串 ?handler=JoinList ,請變更路由,將處理常式名稱放在 url 的路徑部分。If you don't like the query string ?handler=JoinList in the URL, change the route to put the handler name in the path portion of the URL. 您可以藉由新增以雙引號括住的路由範本來自訂路由 @pageThe route can be customized by adding a route template enclosed in double quotes after the @page directive.

@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>

使用上述程式碼,提交至 OnPostJoinListAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH/JoinListUsing the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. 提交至 OnPostJoinListUCAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH/JoinListUCThe URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

跟在 handler 後面的 ? 表示路由參數為選擇性。The ? following handler means the route parameter is optional.

Advanced configuration and settingsAdvanced configuration and settings

大部分的應用程式都不需要下列各節中的設定和設定。The configuration and settings in following sections is not required by most apps.

若要設定 advanced 選項,請使用設定的多載 AddRazorPages RazorPagesOptionsTo configure advanced options, use the AddRazorPages overload that configures RazorPagesOptions:

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
    {
        options.RootDirectory = "/MyPages";
        options.Conventions.AuthorizeFolder("/MyPages/Admin");
    });
}

使用 RazorPagesOptions 設定頁面的根目錄,或新增頁面的應用程式模型慣例。Use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. 如需慣例的詳細資訊,請參閱 Razor 頁面授權慣例For more information on conventions, see Razor Pages authorization conventions.

若要先行編譯視圖,請參閱 Razor view 編譯To precompile views, see Razor view compilation.

指定 Razor 頁面位於內容根目錄Specify that Razor Pages are at the content root

根據預設, Razor 頁面會根目錄在 /Pages 目錄中。By default, Razor Pages are rooted in the /Pages directory. 加入 WithRazorPagesAtContentRoot ,以指定您的 Razor 頁面位於應用程式的 內容根目錄 (ContentRootPath) :Add WithRazorPagesAtContentRoot to specify that your Razor Pages are at the content root (ContentRootPath) of the app:

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        })
        .WithRazorPagesAtContentRoot();
}

指定 Razor 頁面位於自訂根目錄Specify that Razor Pages are at a custom root directory

新增 WithRazorPagesRoot 以指定 Razor 頁面位於應用程式的自訂根目錄, (提供相對路徑) :Add WithRazorPagesRoot to specify that Razor Pages are at a custom root directory in the app (provide a relative path):

public void ConfigureServices(IServiceCollection services)
{            
    services.AddRazorPages(options =>
        {
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        })
        .WithRazorPagesRoot("/path/to/razor/pages");
}

其他資源Additional resources

警告

如果您使用 Visual Studio 2017,請參閱 dotnet/sdk 問題 #3124 (英文),以取得未使用 Visual Studio 的 .NET Core SDK 版本相關資訊。If you use Visual Studio 2017, see dotnet/sdk issue #3124 for information about .NET Core SDK versions that don't work with Visual Studio.

建立 Razor 頁面專案Create a Razor Pages project

如需如何建立頁面專案的詳細指示,請參閱 開始使用 Razor 頁面 Razor 。See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Razor 頁面Razor Pages

Razor 頁面已在 Startup.cs 中啟用:Razor Pages is enabled in Startup.cs:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Includes support for Razor Pages and controllers.
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
    }
}

請考慮使用基本頁面:Consider a basic page:

@page

<h1>Hello, world!</h1>
<h2>The time on the server is @DateTime.Now</h2>

上述程式碼看起來很像是在具有控制器和 views 的 ASP.NET Core 應用程式中使用的 Razor 視圖檔案。The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. 讓它不同的是 @page 指示詞。What makes it different is the @page directive. @page 會將檔案轉換成 MVC 動作,這表示它會直接處理要求,不用透過控制器。@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page 必須是頁面上的第一個指示詞 Razor 。@page must be the first Razor directive on a page. @page 會影響其他結構的行為 Razor 。@page affects the behavior of other Razor constructs.

使用PageModel類別的類似頁面,顯示於下列兩個檔案中。A similar page, using a PageModel class, is shown in the following two files. Pages/Index2.cshtml 檔案:The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model IndexModel2

<h2>Separate page model</h2>
<p>
    @Model.Message
</p>

Pages/Index2.cshtml.cs 頁面模型:The Pages/Index2.cshtml.cs page model:

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 Razor 附加 .cs 的分頁檔相同。By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. 例如,前一 Razor 頁是 Pages/index2.cshtml.cs。For example, the previous Razor Page is Pages/Index2.cshtml. 包含 PageModel 類別的檔案名為 Pages/Index2.cshtml.csThe file containing the PageModel class is named Pages/Index2.cshtml.cs.

頁面的 URL 路徑關聯是由頁面在檔案系統中的位置決定。The associations of URL paths to pages are determined by the page's location in the file system. 下表顯示 Razor 頁面路徑和相符的 URL:The following table shows a Razor Page path and the matching URL:

檔案名稱和路徑File name and path 比對 URLmatching URL
/Pages/Index.cshtml/Pages/Index.cshtml //Index/ or /Index
/Pages/Contact.cshtml/Pages/Contact.cshtml /Contact
/Pages/Store/Contact.cshtml/Pages/Store/Contact.cshtml /Store/Contact
/Pages/Store/Index.cshtml/Pages/Store/Index.cshtml /Store/Store/Index/Store or /Store/Index

注意:Notes:

  • 執行時間預設會 Razor 在 [ pages ] 資料夾中尋找分頁檔。The runtime looks for Razor Pages files in the Pages folder by default.
  • Index 是 URL 未包含頁面時的預設頁面。Index is the default page when a URL doesn't include a page.

撰寫基本表單Write a basic form

Razor 頁面的設計目的是要讓搭配網頁瀏覽器使用的常見模式在建立應用程式時很容易執行。Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. 模型系結 、卷標協助程式和 HTML 協助程式全都 使用頁面類別中定義的屬性 Razor 。Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Contact 模型請考慮實作基本的「與我們連絡」格式頁面:Consider a page that implements a basic "contact us" form for the Contact model:

本文件中的範例,會在 Startup.cs 檔案中初始化 DbContextFor the samples in this document, the DbContext is initialized in the Startup.cs file.

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();
        }
    }
}

資料模型:The data model:

using System.ComponentModel.DataAnnotations;

namespace RazorPagesContacts.Data
{
    public class Customer
    {
        public int Id { get; set; }

        [Required, StringLength(100)]
        public string Name { get; set; }
    }
}

DB 內容:The db context:

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 檢視檔案:The Pages/Create.cshtml view file:

@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 頁面模型:The Pages/Create.cshtml.cs page model:

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,與頁面位於相同的命名空間。By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

PageModel 類別可以分離頁面邏輯與頁面展示。The PageModel class allows separation of the logic of a page from its presentation. 此類別會定義頁面的處理常式,以處理傳送至頁面的要求與用於轉譯頁面的資料。It defines page handlers for requests sent to the page and the data used to render the page. 這種分隔允許:This separation allows:

POST 要求上執行的頁面具有 「處理常式方法」OnPostAsync (當使用者張貼表單時)。The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). 您可以新增任何 HTTP 指令動詞的處理常式方法。You can add handler methods for any HTTP verb. 最常見的處理常式包括:The most common handlers are:

  • OnGet,初始化頁所需要的狀態。OnGet to initialize state needed for the page. OnGet 範例。OnGet sample.
  • OnPost,處理表單提交作業。OnPost to handle form submissions.

Async 命名尾碼是選擇性的,但依照慣例通常用於非同步函式。The Async naming suffix is optional but is often used by convention for asynchronous functions. 上述程式碼一般適用于 Razor 頁面。The preceding code is typical for Razor Pages.

如果您熟悉使用控制器和 views 的 ASP.NET apps:If you're familiar with ASP.NET apps using controllers and views:

  • OnPostAsync上述範例中的程式碼看起來類似一般的控制器程式碼。The OnPostAsync code in the preceding example looks similar to typical controller code.
  • 大部分的 MVC 基本專案,例如 模型系結、 驗證驗證和動作結果都是共用的。Most of the MVC primitives like model binding, validation, Validation, and action results are shared.

前一個 OnPostAsync 方法:The previous OnPostAsync method:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _db.Customers.Add(Customer);
    await _db.SaveChangesAsync();
    return RedirectToPage("/Index");
}

OnPostAsync 的基本流程:The basic flow of OnPostAsync:

檢查驗證錯誤。Check for validation errors.

  • 如果沒有任何錯誤,會儲存資料並重新導向。If there are no errors, save the data and redirect.
  • 如果有錯誤,會再次顯示有驗證訊息的頁面。If there are errors, show the page again with validation messages. 用戶端驗證和傳統的 ASP.NET Core MVC 應用程式完全相同。Client-side validation is identical to traditional ASP.NET Core MVC applications. 在許多情況下,會在用戶端上偵測到驗證錯誤,且永遠不會提交到伺服器。In many cases, validation errors would be detected on the client, and never submitted to the server.

成功輸入資料後,OnPostAsync 處理常式方法會呼叫 RedirectToPage 協助程式方法,傳回 RedirectToPageResult 的執行個體。When the data is entered successfully, the OnPostAsync handler method calls the RedirectToPage helper method to return an instance of RedirectToPageResult. RedirectToPage 是新的動作結果,類似於 RedirectToActionRedirectToRoute,但會針對頁面自訂。RedirectToPage is a new action result, similar to RedirectToAction or RedirectToRoute, but customized for pages. 在上述範例中,它會重新導向至根索引頁面 (/Index)。In the preceding sample, it redirects to the root Index page (/Index). 產生頁面 URL一節會詳細說明 RedirectToPageRedirectToPage is detailed in the URL generation for Pages section.

當提交的表單有驗證錯誤時 (傳遞至伺服器),OnPostAsync 處理常式方法會呼叫 Page 協助程式方法。When the submitted form has validation errors (that are passed to the server), theOnPostAsync handler method calls the Page helper method. Page 會傳回 PageResult 的執行個體。Page returns an instance of PageResult. 傳回 Page 類似於控制站中的動作傳回 ViewReturning Page is similar to how actions in controllers return View. PageResult 這是處理常式方法的預設傳回型別。PageResult is the default return type for a handler method. 傳回 void 的處理常式方法會呈現頁面。A handler method that returns void renders the page.

Customer 屬性 (property) 使用 [BindProperty] 屬性 (attribute) 加入模型繫結。The Customer property uses [BindProperty] attribute to opt in to model binding.

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");
    }
}

Razor 依預設,頁面只會系結具有非動詞命令的屬性 GETRazor Pages, by default, bind properties only with non-GET verbs. 繫結至屬性可以減少您必須撰寫的程式碼數量。Binding to properties can reduce the amount of code you have to write. 透過使用相同的屬性呈現表單欄位 (<input asp-for="Customer.Name">) 並接受輸入,繫結可以減少程式碼。Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

警告

基於安全性考量,您必須選擇將 GET 要求資料繫結到頁面模型屬性。For security reasons, you must opt in to binding GET request data to page model properties. 請先驗證使用者輸入再將其對應至屬性。Verify user input before mapping it to properties. 在處理依賴於GET查詢字串或路由值的方案時,選擇綁定非常有用。Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

要對要求GET結合屬性,請將[BindProperty]屬性的SupportsGet屬性true設定為 :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

有關詳細資訊,請參閱ASP.NET核心社區站立:綁定 GET 討論 (YouTube)For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

首頁 (Index.cshtml):The home page (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>

已建立關聯的 PageModel 類別 (Index.cshtml.cs):The associated PageModel class (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 檔案包含下列標記可為每個連絡人建立編輯連結:The Index.cshtml file contains the following markup to create an edit link for each contact:

<a asp-page="./Edit" asp-route-id="@contact.Id">edit</a>

<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a>錨點標籤協助程式使用 asp-route-{value} 屬性來產生編輯頁面的連結。The <a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> Anchor Tag Helper used the asp-route-{value} attribute to generate a link to the Edit page. 該連結包含路由資料和連絡人識別碼。The link contains route data with the contact ID. 例如: https://localhost:5001/Edit/1For example, https://localhost:5001/Edit/1. 標記 協助程式可讓伺服器端程式碼參與建立和轉譯檔案中的 HTML 元素 Razor 。Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. 標記協助程式由 @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 啟用Tag Helpers are enabled by @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Pages/Edit.cshtml 檔案:The Pages/Edit.cshtml file:

@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}" 指示詞。The first line contains the @page "{id:int}" directive. 路由條件約束 "{id:int}" 通知頁面接受包含 int 路由資料的頁面要求。The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. 如果頁面要求不包含可以轉換成 int 的路由資料,執行階段會傳回 HTTP 404 (找不到) 錯誤。If a request to the page doesn't contain route data that can be converted to an int, the runtime returns an HTTP 404 (not found) error. 若要使識別碼成為選擇性,請將 ? 附加至路由條件約束:To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

Pages/Edit.cshtml.cs 檔案:The Pages/Edit.cshtml.cs file:

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 檔案也包含能夠為每個客戶連絡人建立刪除按鈕的標記:The Index.cshtml file also contains markup to create a delete button for each customer contact:

<button type="submit" asp-page-handler="delete" 
        asp-route-id="@contact.Id">delete</button>

使用 HTML 轉譯刪除按鈕時,其 formaction 會包含下列項目的參數:When the delete button is rendered in HTML, its formaction includes parameters for:

  • asp-route-id 屬性指定的客戶連絡人識別碼。The customer contact ID specified by the asp-route-id attribute.
  • asp-page-handler 屬性指定的 handlerThe handler specified by the asp-page-handler attribute.

以下是轉譯的刪除按鈕範例,內含客戶連絡人識別碼 1Here is an example of a rendered delete button with a customer contact ID of 1:

<button type="submit" formaction="/?id=1&amp;handler=delete">delete</button>

選取按鈕時,表單 POST 要求會傳送至伺服器。When the button is selected, a form POST request is sent to the server. 依照慣例,會依據配置 OnPost[handler]Async,按 handler 參數的值來選取處理常式方法。By convention, the name of the handler method is selected based on the value of the handler parameter according to the scheme OnPost[handler]Async.

在此範例中,因為 handlerdelete,所以會使用 OnPostDeleteAsync 處理常式方法來處理 POST 要求。Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. asp-page-handler 設為其他值 (例如 remove),則會選取名為 OnPostRemoveAsync 的處理常式方法。If the asp-page-handler is set to a different value, such as remove, a handler method with the name OnPostRemoveAsync is selected. 下列程式碼顯示 OnPostDeleteAsync 處理常式:The following code shows the OnPostDeleteAsync handler:

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 方法:The OnPostDeleteAsync method:

  • 接受查詢字串的 idAccepts the id from the query string. 如果 Index. cshtml 頁面指示詞包含路由條件約束 "{id:int?}" ,則 id 會來自路由資料。If the Index.cshtml page directive contained routing constraint "{id:int?}", id would come from route data. 的路由資料 id 是在 URI 中指定,例如 https://localhost:5001/Customers/2The route data for id is specified in the URI such as https://localhost:5001/Customers/2.
  • 使用 FindAsync 在資料庫中查詢客戶連絡人。Queries the database for the customer contact with FindAsync.
  • 若找到客戶連絡人,會從客戶連絡人清單中予以移除。If the customer contact is found, they're removed from the list of customer contacts. 資料庫隨即更新。The database is updated.
  • 呼叫 RedirectToPage 以重新導向至根索引頁 (/Index)。Calls RedirectToPage to redirect to the root Index page (/Index).

將頁面屬性標示為必要Mark page properties as required

上的屬性 PageModel 可以使用 必要 的屬性標記:Properties on a PageModel can be marked with the Required attribute:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;

namespace RazorPagesMovie.Pages.Movies
{
    public class CreateModel : PageModel
    {
        public IActionResult OnGet()
        {
            return Page();
        }

        [BindProperty]
        [Required(ErrorMessage = "Color is required")]
        public string Color { get; set; }

        public IActionResult OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            // Process color.

            return RedirectToPage("./Index");
        }
    }
}

如需詳細資訊,請參閱模型驗證For more information, see Model validation.

使用 OnGet 處理常式後援來處理 HEAD 要求Handle HEAD requests with an OnGet handler fallback

HEAD 要求可讓您擷取特定資源的標頭。HEAD requests allow you to retrieve the headers for a specific resource. 不同於 GET 要求,HEAD 要求不會傳回回應主體。Unlike GET requests, HEAD requests don't return a response body.

一般來說,會為 HEAD 要求建立及呼叫 OnHead 處理常式:Ordinarily, an OnHead handler is created and called for HEAD requests:

public void OnHead()
{
    HttpContext.Response.Headers.Add("HandledBy", "Handled by OnHead!");
}

在 ASP.NET Core 2.1 或更新版本中, Razor OnGet 如果未定義任何處理程式,頁面就會切換回呼叫處理常式 OnHeadIn ASP.NET Core 2.1 or later, Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined. 這個行為藉由在 Startup.ConfigureServices 中呼叫 SetCompatibilityVersion 來啟用:This behavior is enabled by the call to SetCompatibilityVersion in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

預設範本會在 ASP.NET Core 2.1 和 2.2 中產生 SetCompatibilityVersion 呼叫。The default templates generate the SetCompatibilityVersion call in ASP.NET Core 2.1 and 2.2. SetCompatibilityVersion 有效地將 Razor Pages 選項設定 AllowMappingHeadRequestsToGetHandlertrueSetCompatibilityVersion effectively sets the Razor Pages option AllowMappingHeadRequestsToGetHandler to true.

您可以明確選擇「特定」行為,而不必透過 SetCompatibilityVersion 選擇所有行為。Rather than opting in to all behaviors with SetCompatibilityVersion, you can explicitly opt in to specific behaviors. 下列程式碼會選擇讓 HEAD 要求對應到 OnGet 處理常式:The following code opts in to allowing HEAD requests to be mapped to the OnGet handler:

services.AddMvc()
    .AddRazorPagesOptions(options =>
    {
        options.AllowMappingHeadRequestsToGetHandler = true;
    });

XSRF/CSRF 和 Razor PagesXSRF/CSRF and Razor Pages

您不必撰寫任何防偽驗證程式碼。You don't have to write any code for antiforgery validation. Antiforgery 權杖的產生和驗證會自動包含在 Razor 頁面中。Antiforgery token generation and validation are automatically included in Razor Pages.

使用頁面的版面配置、部分、範本和標記協助程式 RazorUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

頁面會使用 view engine 的所有功能 Razor 。Pages work with all the capabilities of the Razor view engine. 配置、部分、範本、標籤協助程式、 _ViewStart cshtml_ViewImports. cshtml 的運作方式與傳統視圖的運作方式相同。 RazorLayouts, partials, templates, Tag Helpers, _ViewStart.cshtml, _ViewImports.cshtml work in the same way they do for conventional Razor views.

可利用這些功能的一部分來整理這個頁面。Let's declutter this page by taking advantage of some of those capabilities.

版面配置頁面新增至 Pages/Shared/_Layout.cshtmlAdd a layout page to Pages/Shared/_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>

版面配置:The Layout:

  • 控制每個頁面的版面配置 (除非頁面退出版面配置)。Controls the layout of each page (unless the page opts out of layout).
  • 匯入 HTML 結構,例如 JavaScript 和樣式表。Imports HTML structures such as JavaScript and stylesheets.

如需詳細資訊,請參閱版面配置頁面See layout page for more information.

版面配置屬性是在 Pages/_ViewStart.cshtml 中設定:The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

版面配置位於 Pages/Shared 資料夾。The layout is in the Pages/Shared folder. 頁面會以階層方式尋找其他檢視 (版面配置、範本、部分),從目前頁面的相同資料夾開始。Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. 頁面/共用 資料夾中的版面配置可以從 Razor [ pages ] 資料夾下的任何頁面使用。A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

版面配置頁面應位於 Pages/Shared 資料夾中。The layout file should go in the Pages/Shared folder.

我們 建議您將配置檔案放入 Views/Shared 資料夾。We recommend you not put the layout file in the Views/Shared folder. Views/Shared 是 MVC 檢視模式。Views/Shared is an MVC views pattern. Razor 頁面的目的是要依賴資料夾階層,不是路徑慣例。Razor Pages are meant to rely on folder hierarchy, not path conventions.

頁面上的視圖搜尋 Razor 包含 Pages 資料夾。View search from a Razor Page includes the Pages folder. 您使用 MVC 控制器和傳統視圖的版面配置、範本和部分, Razor 只是工作The layouts, templates, and partials you're using with MVC controllers and conventional Razor views just work.

新增 Pages/_ViewImports.cshtml 檔案:Add a Pages/_ViewImports.cshtml file:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

本教學課程稍後會說明 @namespace@namespace is explained later in the tutorial. @addTagHelper 指示詞會將 內建標記協助程式帶入 Pages 資料夾中的所有頁面。The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

在頁面上明確使用 @namespace 指示詞時:When the @namespace directive is used explicitly on a page:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

<h2>Name space</h2>
<p>
    @Model.Message
</p>

指示詞會設定頁面的命名空間。The directive sets the namespace for the page. @model 指示詞不需要包含命名空間。The @model directive doesn't need to include the namespace.

@namespace 指示詞包含在 _ViewImports.cshtml 中時,指定的命名空間會在匯入 @namespace 指示詞的頁面中提供所產生之命名空間的前置詞。When the @namespace directive is contained in _ViewImports.cshtml, the specified namespace supplies the prefix for the generated namespace in the Page that imports the @namespace directive. 所產生命名空間的其餘部分 (後置字元部分) 是包含 _ViewImports.cshtml 的資料夾和包含頁面的資料夾之間,以句點分隔的相對路徑。The rest of the generated namespace (the suffix portion) is the dot-separated relative path between the folder containing _ViewImports.cshtml and the folder containing the page.

例如,PageModel 類別 Pages/Customers/Edit.cshtml.cs 會明確地設定命名空間:For example, the PageModel class Pages/Customers/Edit.cshtml.cs explicitly sets the namespace:

namespace RazorPagesContacts.Pages
{
    public class EditModel : PageModel
    {
        private readonly AppDbContext _db;

        public EditModel(AppDbContext db)
        {
            _db = db;
        }

        // Code removed for brevity.

Pages/_ViewImports.cshtml 檔案會設定下列命名空間:The Pages/_ViewImports.cshtml file sets the following namespace:

@namespace RazorPagesContacts.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

針對 Pages/Customers/Edit. cshtml 頁面產生的命名空間與 Razor PageModel 類別相同。The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace也可搭配傳統 Razor 視圖使用。@namespace also works with conventional Razor views.

原始的 Pages/Create.cshtml 檢視檔案:The original Pages/Create.cshtml view file:

@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 檢視檔案:The updated Pages/Create.cshtml view file:

@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>

Razor Pages 入門專案包含 pages/_ValidationScriptsPartial. cshtml,可連結用戶端驗證。The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

如需部分檢視的詳細資訊,請參閱 ASP.NET Core 中的部分檢視For more information on partial views, see ASP.NET Core 中的部分檢視.

產生頁面 URLURL generation for Pages

前面出現過的 Create 頁面使用 RedirectToPageThe Create page, shown previously, uses RedirectToPage:

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _db.Customers.Add(Customer);
    await _db.SaveChangesAsync();
    return RedirectToPage("/Index");
}

應用程式有下列檔案/資料夾結構:The app has the following file/folder structure:

  • /Pages/Pages

    • Index.cshtmlIndex.cshtml

    • /Customers/Customers

      • Create.cshtmlCreate.cshtml
      • Edit.cshtmlEdit.cshtml
      • Index.cshtmlIndex.cshtml

Pages/Customers/Create.cshtmlPages/Customers/Edit.cshtml 頁面在成功後會重新導向至 Pages/Index.cshtmlThe Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Index.cshtml after success. 字串 /Index 為 URI 的一部分,可存取前一個頁面。The string /Index is part of the URI to access the preceding page. 字串 /Index 可以用來產生 Pages/Index.cshtml 頁面的 URI。The string /Index can be used to generate URIs to the Pages/Index.cshtml page. 例如:For example:

  • Url.Page("/Index", ...)
  • <a asp-page="/Index">My Index Page</a>
  • RedirectToPage("/Index")

頁面名稱是從根 /Pages 資料夾到該頁面的路徑 (包括前置的 /,例如 /Index)。The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). 上述 URL 產生範例,透過硬式編碼的 URL 提供更加優異的選項與功能。The preceding URL generation samples offer enhanced options and functional capabilities over hardcoding a URL. URL 產生使用路由,可以根據路由在目的地路徑中定義的方式,產生並且編碼參數。URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

產生頁面 URL 支援相關的名稱。URL generation for pages supports relative names. 下表顯示從 Pages/Customers/Create.cshtml 以不同的 RedirectToPage 參數選取的索引頁:The following table shows which Index page is selected with different RedirectToPage parameters from Pages/Customers/Create.cshtml:

RedirectToPage(x)RedirectToPage(x) 頁面Page
RedirectToPage("/Index")RedirectToPage("/Index") Pages/IndexPages/Index
RedirectToPage("./Index");RedirectToPage("./Index"); Pages/Customers/IndexPages/Customers/Index
RedirectToPage("../Index")RedirectToPage("../Index") Pages/IndexPages/Index
RedirectToPage("Index")RedirectToPage("Index") Pages/Customers/IndexPages/Customers/Index

RedirectToPage("Index")RedirectToPage("./Index")RedirectToPage("../Index") 是「相對名稱」。RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. RedirectToPage 參數「結合」了目前頁面的路徑,以計算目的地頁面的名稱。The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

相對名稱連結在以複雜結構建置網站時很有用。Relative name linking is useful when building sites with a complex structure. 如果您使用相對名稱連結資料夾中的頁面,您可以重新命名該資料夾。If you use relative names to link between pages in a folder, you can rename that folder. 所有連結仍可運作 (因為它們不包含資料夾名稱)。All the links still work (because they didn't include the folder name).

若要重新導向到不同區域中的頁面,請指定區域:To redirect to a page in a different Area, specify the area:

RedirectToPage("/Index", new { area = "Services" });

如需詳細資訊,請參閱ASP.NET Core 中的區域For more information, see ASP.NET Core 中的區域.

ViewData 屬性ViewData attribute

資料可以傳遞至具有 ViewDataAttribute 的頁面。Data can be passed to a page with ViewDataAttribute. Razor具有屬性之控制器或頁面模型上的屬性 [ViewData] 會從>viewdatadictionary儲存和載入其值。Properties on controllers or Razor Page models with the [ViewData] attribute have their values stored and loaded from the ViewDataDictionary.

在下列範例中, AboutModel 包含標示為的 Title 屬性 [ViewData]In the following example, the AboutModel contains a Title property marked with [ViewData]. Title 屬性會設定為 [關於] 頁面的標題:The Title property is set to the title of the About page:

public class AboutModel : PageModel
{
    [ViewData]
    public string Title { get; } = "About";

    public void OnGet()
    {
    }
}

在 [關於] 頁面上,存取 Title 屬性作為模型屬性:In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

在此配置中,標題會從 ViewData 字典中讀取:In the layout, the title is read from the ViewData dictionary:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

TempDataTempData

ASP.NET Core 公開控制器上的 TempData 屬性。ASP.NET Core exposes the TempData property on a controller. 這個屬性會儲存資料,直到讀取為止。This property stores data until it's read. KeepPeek 方法可以用來檢查資料,不用刪除。The Keep and Peek methods can be used to examine the data without deletion. 當有多個要求需要資料時,TempData 對重新導向很有幫助。TempData is useful for redirection, when data is needed for more than a single request.

下列程式碼會設定使用 TempDataMessage 值:The following code sets the value of Message using TempData:

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 檔案中的下列標記會顯示使用 TempDataMessage 值。The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

<h3>Msg: @Model.Message</h3>

Pages/Customers/Index.cshtml.cs 頁面模型會將 [TempData] 屬性 (attribute) 套用到 Message 屬性 (property)。The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

[TempData]
public string Message { get; set; }

如需詳細資訊,請參閱 TempDataFor more information, see TempData .

每頁面有多個處理常式Multiple handlers per page

下列頁面會使用 asp-page-handler 標記協助程式為兩個處理常式產生標記:The following page generates markup for two handlers using the asp-page-handler Tag Helper:

@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>

上例中的表單有兩個提交按鈕,每一個都使用 FormActionTagHelper 提交至不同的 URL。The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. asp-page-handler 屬性附隨於 asp-pageThe asp-page-handler attribute is a companion to asp-page. asp-page-handler 產生的 URL 會提交至頁面所定義的每一個處理常式方法。asp-page-handler generates URLs that submit to each of the handler methods defined by a page. 因為範例連結至目前的頁面,所以未指定 asp-pageasp-page isn't specified because the sample is linking to the current page.

頁面模型:The page model:

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?.ToUpperInvariant();
            return await OnPostJoinListAsync();
        }
    }
}

上述程式碼使用「具名的處理常式方法」。The preceding code uses named handler methods. 具名的處理常式方法的建立方式是採用名稱中在 On<HTTP Verb> 後面、Async 之前 (如有) 的文字。Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). 在上例中,頁面方法是 OnPost JoinList Async 和 OnPost JoinListUC Async。In the preceding example, the page methods are OnPost JoinList Async and OnPost JoinListUC Async. 移除 OnPostAsync,處理常式名稱就是 JoinListJoinListUCWith OnPost and Async removed, the handler names are JoinList and JoinListUC.

<input type="submit" asp-page-handler="JoinList" value="Join" />
<input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />

使用上述程式碼,提交至 OnPostJoinListAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH?handler=JoinListUsing the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinList. 提交至 OnPostJoinListUCAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH?handler=JoinListUCThe URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

自訂路由Custom routes

使用 @page 指示詞,可以:Use the @page directive to:

  • 指定頁面的自訂路由。Specify a custom route to a page. 例如,[關於] 頁面的路由可使用 @page "/Some/Other/Path" 設為 /Some/Other/PathFor example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • 將區段附加到頁面的預設路由。Append segments to a page's default route. 例如,使用 @page "item" 可將 "item" 區段新增到頁面的預設路由。For example, an "item" segment can be added to a page's default route with @page "item".
  • 將參數附加到頁面的預設路由。Append parameters to a page's default route. 例如,具有 @page "{id}" 的頁面可要求識別碼參數 idFor example, an ID parameter, id, can be required for a page with @page "{id}".

支援在路徑開頭以波狀符號 (~) 指定根相對路徑。A root-relative path designated by a tilde (~) at the beginning of the path is supported. 例如,@page "~/Some/Other/Path"@page "/Some/Other/Path" 相同。For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

如果您不喜歡 URL 中的查詢字串 ?handler=JoinList ,請變更路由,將處理常式名稱放在 url 的路徑部分。If you don't like the query string ?handler=JoinList in the URL, change the route to put the handler name in the path portion of the URL. 您可以藉由新增以雙引號括住的路由範本來自訂路由 @pageThe route can be customized by adding a route template enclosed in double quotes after the @page directive.

@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>

使用上述程式碼,提交至 OnPostJoinListAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH/JoinListUsing the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. 提交至 OnPostJoinListUCAsync 的 URL 路徑是 https://localhost:5001/Customers/CreateFATH/JoinListUCThe URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

跟在 handler 後面的 ? 表示路由參數為選擇性。The ? following handler means the route parameter is optional.

組態與設定Configuration and settings

若要設定進階選項,請在 MVC 產生器上使用擴充方法 AddRazorPagesOptionsTo configure advanced options, use the extension method AddRazorPagesOptions on the MVC builder:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.RootDirectory = "/MyPages";
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        });
}

目前可以使用 RazorPagesOptions 設定頁面的根目錄,或新增頁面的應用程式模型慣例。Currently you can use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. 我們將在未來以這種方式獲得更多的擴充性。We'll enable more extensibility this way in the future.

若要先行編譯視圖,請參閱 Razor view 編譯To precompile views, see Razor view compilation .

下載或檢視範例程式碼Download or view sample code.

請參閱這篇簡介中的 開始使用 Razor 頁面See Get started with Razor Pages, which builds on this introduction.

指定 Razor 頁面位於內容根目錄Specify that Razor Pages are at the content root

根據預設, Razor 頁面會根目錄在 /Pages 目錄中。By default, Razor Pages are rooted in the /Pages directory. Razor PagesAtContentRoot 新增至 >addmvc ,以指定您的 Razor 頁面位於應用程式的 內容根目錄 (ContentRootPath) :Add WithRazorPagesAtContentRoot to AddMvc to specify that your Razor Pages are at the content root (ContentRootPath) of the app:

services.AddMvc()
    .AddRazorPagesOptions(options =>
    {
        ...
    })
    .WithRazorPagesAtContentRoot();

指定 Razor 頁面位於自訂根目錄Specify that Razor Pages are at a custom root directory

Razor PagesRoot 新增至 >addmvc ,以指定您 Razor 的頁面位於應用程式中的自訂根目錄, (提供相對路徑) :Add WithRazorPagesRoot to AddMvc to specify that your Razor Pages are at a custom root directory in the app (provide a relative path):

services.AddMvc()
    .AddRazorPagesOptions(options =>
    {
        ...
    })
    .WithRazorPagesRoot("/path/to/razor/pages");

其他資源Additional resources