Einführung in Razor Pages in ASP.NET CoreIntroduction to Razor Pages in ASP.NET Core

Von Rick Anderson und Ryan NowakBy Rick Anderson and Ryan Nowak

Razor Pages kann im Vergleich zu Controllern und Ansichten das Programmieren seitenbasierter Anwendungen vereinfachen und die Produktivität erhöhen.Razor Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

Ein Tutorial, in dem der Model-View-Controller-Ansatz verwendet wird, finden Sie unter Erste Schritte mit ASP.NET Core MVC und Visual Studio.If you're looking for a tutorial that uses the Model-View-Controller approach, see Get started with ASP.NET Core MVC.

Dieses Dokument bietet eine Einführung in Razor Pages.This document provides an introduction to Razor Pages. Es handelt sich nicht um ein Schritt-für-Schritt-Tutorial.It's not a step by step tutorial. Wenn es Ihnen Probleme bereitet, die Ausführungen in einigen Abschnitten nachzuvollziehen, lesen Sie Erste Schritte mit Razor Pages in ASP.NET Core.If you find some of the sections too advanced, see Get started with Razor Pages. Eine Übersicht über ASP.NET Core finden Sie unter Einführung in ASP.NET Core.For an overview of ASP.NET Core, see the Introduction to ASP.NET Core.

VoraussetzungenPrerequisites

Erstellen eines Razor Pages-ProjektsCreate a Razor Pages project

Ausführliche Informationen zum Erstellen eines Razor Pages-Projekts finden Sie unter Erste Schritte mit Razor Pages.See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Razor PagesRazor Pages

Razor Pages ist in Startup.cs aktiviert: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();
        });
    }
}

Sehen Sie sich diese einfache Seite an: Consider a basic page:

@page

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

Der vorherige Code ähnelt sehr einer Razor-Ansichtsdatei, die in einer ASP.NET Core-App mit Controllern und Ansichten verwendet wird.The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. Der Unterschied besteht in der @page-Anweisung.What makes it different is the @page directive. @page macht die Datei zu einer MVC-Aktion, d.h. dass Anfragen direkt ohne einen Controller verarbeitet werden.@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page muss die erste Razor-Anweisung auf einer Seite sein.@page must be the first Razor directive on a page. @page wirkt sich auf das Verhalten aller anderen Razor-Konstrukte aus.@page affects the behavior of other Razor constructs. Razor Pages-Dateinamen haben das Suffix .cshtml.Razor Pages file names have a .cshtml suffix.

Eine ähnliche Seite, die die PageModel-Klasse verwendet, wird in den folgenden zwei Dateien angezeigt.A similar page, using a PageModel class, is shown in the following two files. Die Datei Pages/Index2.cshtml:The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model Index2Model

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

Das Seitenmodell 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 }";
        }
    }
}

Die PageModel-Klassendatei hat standardmäßig den gleichen Namen wie die Datei mit Razor Pages, nur dass außerdem .cs angefügt wird.By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. Die vorherige Datei mit Razor Razor lautet beispielsweise Pages/Index2.cshtml.For example, the previous Razor Page is Pages/Index2.cshtml. Die Datei mit der PageModel-Klasse heißt Pages/Index2.cshtml.cs.The file containing the PageModel class is named Pages/Index2.cshtml.cs.

Die Zuordnungen von URL-Pfaden zu Seiten werden durch den Speicherort der Seite im Dateisystem bestimmt.The associations of URL paths to pages are determined by the page's location in the file system. Die folgende Tabelle zeigt einen Pfad zu Razor Pages und die entsprechende URL:The following table shows a Razor Page path and the matching URL:

Dateiname und PfadFile name and path Entsprechende URLmatching URL
/Pages/Index.cshtml/Pages/Index.cshtml / oder /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 oder /Store/Index/Store or /Store/Index

Notizen:Notes:

  • Die Runtime sucht standardmäßig im Ordner Pages (Seiten) nach Dateien mit RRazor Pages.The runtime looks for Razor Pages files in the Pages folder by default.
  • Wenn eine Seite nicht in einer URL enthalten ist, ist Index die Standardseite.Index is the default page when a URL doesn't include a page.

Schreiben eines einfachen FormularsWrite a basic form

Razor Pages ist darauf ausgelegt, allgemeine Muster, die mit Webbrowsern verwendet werden können, beim Erstellen einer App leichter implementieren zu können.Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. Die Modellbindung, Taghilfsprogramme und alle HTML-Hilfsprogramme funktionieren nur mit den Eigenschaften, die in einer Klasse der Razor Pages definiert wurden.Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Nehmen wir z.B. eine Seite, die ein allgemeines Kontaktformular für das Contact-Modell implementiert:Consider a page that implements a basic "contact us" form for the Contact model:

Für die Beispiele in diesem Dokument wird DbContext in der Datei Startup.cs initialisiert.For the samples in this document, the DbContext is initialized in the Startup.cs file.

Für die In-Memory-Datenbank ist das NuGet-Paket Microsoft.EntityFrameworkCore.InMemory erforderlich.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();
}

Das Datenmodell: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; }
    }
}

Der db-Kontext: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; }
    }
}

Die Umgebungsdatei 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>

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

Die PageModel -Klasse heißt standardmäßig <PageName>Model und befindet sich im selben Namespace wie die Seite.By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

Mit der Klasse PageModel kann die Logik einer Seite von deren Darstellung getrennt werden.The PageModel class allows separation of the logic of a page from its presentation. Sie definiert Seitenhandler für Anforderungen, die an die Seite geschickt wurden, und für zum Rendern der Seite verwendete Daten.It defines page handlers for requests sent to the page and the data used to render the page. Diese Trennung ermöglicht Folgendes:This separation allows:

Die Seite verfügt über eine OnPostAsync-Handlermethode, die bei POST-Anforderungen ausgeführt wird (wenn ein Benutzer das Formular sendet).The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). Für alle HTTP-Verben können Handlermethoden hinzugefügt werden.Handler methods for any HTTP verb can be added. Die am häufigsten verwendeten Handler sind:The most common handlers are:

  • OnGet, um den für eine Seite erforderlichen Status zu initialisieren.OnGet to initialize state needed for the page. Im vorangehenden Code wird die Razor-Seite CreateModel.cshtml durch die OnGet-Methode dargestellt.In the preceding code, the OnGet method displays the CreateModel.cshtml Razor Page.
  • OnPost, um Formularübermittlungen zu behandelnOnPost to handle form submissions.

Das Namenssuffix Async ist optional. Es wird jedoch standardmäßig häufig für asynchrone Funktionen verwendet.The Async naming suffix is optional but is often used by convention for asynchronous functions. Der vorhergehende Code ist typisch für Razor Pages.The preceding code is typical for Razor Pages.

Wenn Sie mit ASP.NET-Apps vertraut sind, die Controller und Ansichten verwenden, werden Ihnen folgende Fakten bekannt vorkommen:If you're familiar with ASP.NET apps using controllers and views:

  • Der OnPostAsync-Code im vorangehenden Beispiel ähnelt dem typischen Controllercode.The OnPostAsync code in the preceding example looks similar to typical controller code.
  • Die meisten primitiven MVC-Typen wie solche für Modellbindungen, Validierungen und Aktionsergebnisse werden in Controllern und Razor Pages auf dieselbe Weise eingesetzt.Most of the MVC primitives like model binding, validation, and action results work the same with Controllers and Razor Pages.

Die vorherige OnPostAsync-Methode:The previous OnPostAsync method:

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

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

    return RedirectToPage("./Index");
}

Der grundlegende Ablauf von OnPostAsync:The basic flow of OnPostAsync:

Prüfen auf ValidierungsfehlerCheck for validation errors.

  • Wenn keine Fehler vorliegen, werden die Daten gespeichert und weitergeleitet.If there are no errors, save the data and redirect.
  • Wenn es Fehler gibt, zeigen Sie die Seite erneut mit den Validierungsmeldungen an.If there are errors, show the page again with validation messages. denn Validierungsfehler werden oftmals auf dem Client erkannt und nie an den Server übermittelt.In many cases, validation errors would be detected on the client, and never submitted to the server.

Die Umgebungsdatei 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>

Der von Pages/Create.cshtml gerenderte HTML-Code sieht wie folgt aus: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>

Im vorherigen Code gilt für die Formularübermittlung mittels POST Folgendes:In the previous code, posting the form:

  • Bei gültigen Daten:With valid data:

    • Die OnPostAsync-Handlermethode ruft die RedirectToPage-Hilfsmethode auf.The OnPostAsync handler method calls the RedirectToPage helper method. RedirectToPage gibt eine Instanz von RedirectToPageResult zurück.RedirectToPage returns an instance of RedirectToPageResult. RedirectToPage:RedirectToPage:

      • ist ein Aktionsergebnis.Is an action result.
      • ähnelt RedirectToAction oder RedirectToRoute (wird in Controllern und Ansichten verwendet).Is similar to RedirectToAction or RedirectToRoute (used in controllers and views).
      • ist an Seiten angepasst.Is customized for pages. Im vorhergehenden Beispiel leitet es an die Stammindexseite (/Index) weiter.In the preceding sample, it redirects to the root Index page (/Index). Informationen zu RedirectToPage finden Sie im Abschnitt URL-Generierung für Seiten.RedirectToPage is detailed in the URL generation for Pages section.
  • Bei Validierungsfehlern, die an den Server übermittelt werden:With validation errors that are passed to the server:

    • Die OnPostAsync-Handlermethode ruft die Page-Hilfsmethode auf.The OnPostAsync handler method calls the Page helper method. Page gibt eine Instanz von PageResult zurück.Page returns an instance of PageResult. Der Vorgang, bei dem Page zurückgegeben wird, ähnelt dem Vorgang, bei dem Aktionen im Controller View zurückgeben.Returning Page is similar to how actions in controllers return View. PageResult ist der Standardrückgabetyp für eine Handlermethode.PageResult is the default return type for a handler method. Eine Handlermethode, die void zurückgibt, rendert die Seite.A handler method that returns void renders the page.
    • Wenn im vorangehenden Beispiel das Formular mithilfe von POST übermittelt und dabei kein Wert angegeben wird, gibt ModelState.IsValid „false“ zurück.In the preceding example, posting the form with no value results in ModelState.IsValid returning false. In diesem Beispiel werden keine Validierungsfehler auf dem Client angezeigt.In this sample, no validation errors are displayed on the client. Die Verarbeitung von Validierungsfehlern wird weiter unten in diesem Artikel behandelt.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");
    }
    
  • Bei Validierungsfehlern, die durch eine clientseitige Validierung erkannt werden:With validation errors detected by client side validation:

    • Die Daten werden nicht per POST an den Server gesendet.Data is not posted to the server.
    • Die clientseitige Validierung wird weiter unten in diesem Artikel erläutert.Client-side validation is explained later in this document.

Die Eigenschaft Customer verwendet das [BindProperty]-Attribut, um die Modellbindung zu aktivieren: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] sollte nicht in Modellen mit Eigenschaften verwendet werden, die vom Client nicht geändert werden dürfen.[BindProperty] should not be used on models containing properties that should not be changed by the client. Weitere Informationen finden Sie unter Overposting.For more information, see Overposting.

Razor Pages binden Eigenschaften standardmäßig nur an Nicht-GET-Verben.Razor Pages, by default, bind properties only with non-GET verbs. Durch die Bindung an Eigenschaften entfällt das Schreiben von Code, mit dem HTTP-Daten in den Modelltyp konvertiert werden.Binding to properties removes the need to writing code to convert HTTP data to the model type. Die Bindung reduziert den Code mithilfe der gleichen Eigenschaft, um Formularfelder (<input asp-for="Customer.Name">) zu rendern und die Eingabe zu akzeptieren.Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

Warnung

Aus Sicherheitsgründen müssen Sie Daten von GET-Anforderungen in die Seitenmodelleigenschaften einbinden.For security reasons, you must opt in to binding GET request data to page model properties. Überprüfen Sie die Benutzereingaben, bevor Sie sie den Eigenschaften zuordnen.Verify user input before mapping it to properties. Die Verwendung der GET-Bindung ist von Vorteil, wenn Sie Szenarios behandeln, die von Abfragezeichenfolgen oder Routenwerten abhängig sind.Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

Legen Sie die SupportsGet-Eigenschaft des [BindProperty]-Attributs auf true fest, um eine Eigenschaft an GET-Anforderungen zu binden:To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Weitere Informationen finden Sie im Video ASP.NET Core Community Standup: Bind on GET discussion (YouTube) (ASP.NET Core Community Standup: Diskussion zur Bindung an GET).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Sehen Sie sich die Ansichtsdatei Pages/Create.cshtml an: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>
  • Im vorangehenden Code bindet das Eingabetag-Hilfsprogramm <input asp-for="Customer.Name" /> das HTML-Element <input> an den Modellausdruck 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 stellt Taghilfsprogramme zur Verfügung.@addTagHelper makes Tag Helpers available.

Die HomepageThe home page

Index.cshtml ist die Homepage: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>

Die zugeordnete PageModel-Klasse (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();
    }
}

Die Datei Index.cshtml enthält das folgende Markup:The Index.cshtml file contains the following markup:

<td>

Das Anchor-Taghilfsprogramm <a /a> verwendet das asp-route-{value}-Attribut, um einen Link zur Bearbeitungsseite zu generieren.The <a /a> Anchor Tag Helper used the asp-route-{value} attribute to generate a link to the Edit page. Der Link enthält die Routendaten mit der Kontakt-ID.The link contains route data with the contact ID. Beispielsweise https://localhost:5001/Edit/1.For example, https://localhost:5001/Edit/1. Taghilfsprogramme ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien.Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.

Die Datei Index.cshtml enthält das Markup zum Erstellen der Schaltfläche „delete“ (Löschen) für jeden Kundenkontakt: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"

Der gerenderte HTML-Code sieht wie folgt aus:The rendered HTML:

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

Wenn die „delete“-Schaltfläche in HTML gerendert wird, enthält das zugehörige formaction-Element Parameter für Folgendes:When the delete button is rendered in HTML, its formaction includes parameters for:

  • die Kundenkontakt-ID, die durch das asp-route-id-Attribut angegeben wirdThe customer contact ID, specified by the asp-route-id attribute.
  • den handler, der durch das asp-page-handler-Attribut angegeben wirdThe handler, specified by the asp-page-handler attribute.

Wenn die Schaltfläche ausgewählt wird, wird eine POST-Anforderung an den Server gesendet.When the button is selected, a form POST request is sent to the server. Durch Konvention wird der Name der Handlermethode auf Grundlage des Werts des handler-Parameters gemäß dem Schema OnPost[handler]Async ausgewählt.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.

Da der handler in diesem Beispiel delete ist, wird die Handlermethode OnPostDeleteAsync verwendet, um die POST-Anforderung zu verarbeiten.Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. Wenn asp-page-handler auf einen anderen Wert (z. B. remove) festgelegt wird, wird eine Handlermethode namens OnPostRemoveAsync ausgewählt.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();
}

Die OnPostDeleteAsync-Methode:The OnPostDeleteAsync method:

  • ruft die id der Abfragezeichenfolge ab.Gets the id from the query string.
  • Fragt mit FindAsync die Datenbank nach dem Kundenkontakt ab.Queries the database for the customer contact with FindAsync.
  • Wenn der Kundenkontakt gefunden wird, wird er entfernt, und die Datenbank wird aktualisiert.If the customer contact is found, it's removed and the database is updated.
  • Ruft RedirectToPage auf, um die Stammindexseite (/Index) umzuleiten.Calls RedirectToPage to redirect to the root Index page (/Index).

Die Datei „Edit.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>

Die erste Zeile enthält die @page "{id:int}"-Anweisung.The first line contains the @page "{id:int}" directive. Die Routingbeschränkung "{id:int}" weist die Seite an, die Anforderungen für die Seite zu akzeptieren, die int-Routingdaten enthalten.The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. Wenn eine Anforderung an die Seite bestimmte Routingdaten nicht enthält, die in einen int konvertiert werden können, gibt die Runtime einen Fehler vom Typ „HTTP 404: Nicht gefunden“ zurück.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. Um die ID optional zu machen, fügen Sie ? an die Routeneinschränkung an:To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

Die Datei Edit.cshtml.cs sieht wie folgt aus: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");
    }

}

ValidierungValidation

Für Validierungsregeln gilt Folgendes:Validation rules:

  • Sie werden deklarativ in der Modellklasse angegeben.Are declaratively specified in the model class.
  • Sie werden überall in der App erzwungen.Are enforced everywhere in the app.

Der Namespace System.ComponentModel.DataAnnotations stellt eine Gruppe integrierter Validierungsattribute bereit, die deklarativ auf eine Klasse oder Eigenschaft angewendet werden.The System.ComponentModel.DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. „DataAnnotations“ enthält auch Formatierungsattribute wie [DataType], die bei der Formatierung helfen und keinerlei Validierung bereitstellen.DataAnnotations also contains formatting attributes like [DataType] that help with formatting and don't provide any validation.

Sehen Sie sich das Customer-Modell an: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; }
    }
}

Für die folgende Ansichtsdatei Create.cshtml gilt Folgendes: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>

Der vorangehende Code:The preceding code:

  • umfasst jQuery-Skripts einschließlich solcher zur Validierung.Includes jQuery and jQuery validation scripts.

  • Verwendet die Taghilfsprogramme <div /> und <span />, um Folgendes zu ermöglichen:Uses the <div /> and <span /> Tag Helpers to enable:

    • clientseitiger Validierung.Client-side validation.
    • Rendering von Validierungsfehlern.Validation error rendering.
  • wird der folgende HTML-Code generiert: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>
    

Wenn Sie das Formular „Create“ (Erstellen) ohne einen Wert für den Namen mit POST übermitteln, wird die Fehlermeldung „The Name field is required.“ (Für das Namensfeld muss ein Wert angegeben werden.)Posting the Create form without a name value displays the error message "The Name field is required." auf dem Formular angezeigt.on the form. Wenn JavaScript auf dem Client aktiviert ist, zeigt der Browser den Fehler an, ohne dass Daten per POST an den Server gesendet werden.If JavaScript is enabled on the client, the browser displays the error without posting to the server.

Das [StringLength(10)]-Attribut generiert data-val-length-max="10" für den gerenderten HTML-Code.The [StringLength(10)] attribute generates data-val-length-max="10" on the rendered HTML. data-val-length-max verhindert, dass im Browser ein Wert eingegeben wird, der die angegebene Maximallänge überschreitet.data-val-length-max prevents browsers from entering more than the maximum length specified. Wenn ein Tool wie Fiddler zum Bearbeiten und erneuten Senden einer POST-Anforderung verwendet wirdIf a tool such as Fiddler is used to edit and replay the post:

  • und die Länge des Namens 10 Zeichen überschreitet,With the name longer than 10.
  • geschieht Folgendes: Die Fehlermeldung „The field Name must be a string with a maximum length of 10.“ (Das Namensfeld muss eine Zeichenfolge mit maximal 10 Zeichen enthalten.)The error message "The field Name must be a string with a maximum length of 10." wird zurückgegeben.is returned.

Sehen Sie sich das folgende Movie-Modell an: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; }
    }

Die Validierungsattribute geben das Verhalten an, das für die Modelleigenschaften erzwungen werden soll:The validation attributes specify behavior to enforce on the model properties they're applied to:

  • Die Attribute Required und MinimumLength geben an, dass eine Eigenschaft einen Wert haben muss. Ein Benutzer kann allerdings ein Leerzeichen eingeben, um diese Anforderung zu erfüllen.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.

  • Das Attribut RegularExpression wird verwendet, um einzuschränken, welche Zeichen eingegeben werden dürfen.The RegularExpression attribute is used to limit what characters can be input. Für „Genre“ im Code oben gilt Folgendes:In the preceding code, "Genre":

    • Es dürfen nur Buchstaben enthalten sein.Must only use letters.
    • Der erste Buchstabe muss ein Großbuchstabe sein.The first letter is required to be uppercase. Leerzeichen, Zahlen und Sonderzeichen sind nicht zulässig.White space, numbers, and special characters are not allowed.
  • Für RegularExpression-„Rating“ (Bewertung) gilt Folgendes:The RegularExpression "Rating":

    • Das erste Zeichen muss ein Großbuchstabe sein.Requires that the first character be an uppercase letter.
    • Sonderzeichen und Zahlen sind als darauffolgende Zeichen zulässig.Allows special characters and numbers in subsequent spaces. „PG-13“ ist als Bewertung („Rating“) gültig, nicht jedoch als „Genre“."PG-13" is valid for a rating, but fails for a "Genre".
  • Das Attribut Range schränkt einen Wert auf einen bestimmten Bereich ein.The Range attribute constrains a value to within a specified range.

  • Mit dem Attribut StringLength kann die maximale Länge einer Zeichenfolgeneigenschaft und optional die minimale Länge festlegt werden.The StringLength attribute sets the maximum length of a string property, and optionally its minimum length.

  • Werttypen (wie decimal, int, float, DateTime) sind grundsätzlich erforderlich und benötigen nicht das Attribut [Required].Value types (such as decimal, int, float, DateTime) are inherently required and don't need the [Required] attribute.

Auf der Seite „Create“ (Erstellen) für das Movie-Modell werden ungültige Werte und die daraus resultierenden Fehler angezeigt:The Create page for the Movie model shows displays errors with invalid values:

Ansichtsformular „Movie“ mit mehreren clientseitigen jQuery-Validierungsfehlern

Weitere Informationen finden Sie unter:For more information, see:

Verarbeiten von HEAD-Anforderungen mit einem OnGet-HandlerfallbackHandle HEAD requests with an OnGet handler fallback

HEAD-Anforderungen ermöglichen das Abrufen der Header für eine bestimmte Ressource.HEAD requests allow retrieving the headers for a specific resource. Im Gegensatz zu GET-Anforderungen geben HEAD-Anforderungen keinen Antworttext zurück.Unlike GET requests, HEAD requests don't return a response body.

Normalerweise wird ein OnHead-Handler erstellt und für HEAD-Anforderungen aufgerufen:Ordinarily, an OnHead handler is created and called for HEAD requests:

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

Razor Pages ruft den OnGet-Handler auf, wenn kein OnHead-Handler definiert ist.Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined.

XSRF/CSRF und Razor PagesXSRF/CSRF and Razor Pages

Razor Pages wird durch Validierungsmaßnahmen vor XSRF/CSRF-Angriffen geschützt.Razor Pages are protected by Antiforgery validation. Das Formulartag-Hilfsprogramm injiziert Anti-XSRF/CSRF-Token in HTML-Formularelemente.The FormTagHelper injects antiforgery tokens into HTML form elements.

Verwenden von Layouts, Teilansichten, Vorlagen und Taghilfsprogrammen mit Razor PagesUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

Razor Pages beinhaltet alle Funktionen der Razor-Anzeige-Engine.Pages work with all the capabilities of the Razor view engine. Layouts, Teilansichten, Vorlagen, Taghilfsprogramme, _ViewStart.cshtml und _ViewImports.cshtml funktionieren auf die gleiche Weise wie für herkömmliche Razor-Ansichten.Layouts, partials, templates, Tag Helpers, _ViewStart.cshtml, and _ViewImports.cshtml work in the same way they do for conventional Razor views.

Strukturieren Sie diese Seite mit einigen dieser praktischen Funktionen.Let's declutter this page by taking advantage of some of those capabilities.

Fügen Sie der Pages/Shared/_Layout.cshtml eine Layoutseite hinzu:Add 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>

Das Layout:The Layout:

  • Steuert das Layout der einzelnen Seiten, es sei denn, das Layout wird für eine Seite deaktiviert.Controls the layout of each page (unless the page opts out of layout).
  • Importiert HTML-Strukturen, z.B. JavaScript und Stylesheets.Imports HTML structures such as JavaScript and stylesheets.
  • Der Inhalt der Razor-Seite wird gerendert, wenn @RenderBody() aufgerufen wird.The contents of the Razor page are rendered where @RenderBody() is called.

Weitere Informationen finden Sie unter Layoutseite.For more information, see layout page.

Die Eigenschaft Layout wird in Pages/_ViewStart.cshtml festgelegt:The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

Das Layout befindet sich im Ordner Pages/Shared.The layout is in the Pages/Shared folder. Seiten suchen hierarchisch nach anderen Ansichten (Layouts, Vorlagen oder Teilansichten) und beginnen im gleichen Ordner wie die aktuelle Seite.Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. Ein Layout im Ordner Pages/Shared kann von jeder Razor-Seite aus unter dem Ordner Pages verwendet werden.A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

Die Layoutdatei sollte im Ordner Pages/Shared gespeichert werden.The layout file should go in the Pages/Shared folder.

Wir empfehlen Ihnen, die Layoutdatei nicht im Ordner Views/Shared (Ansichten/Freigegeben) zu platzieren.We recommend you not put the layout file in the Views/Shared folder. Views/Shared ist ein MVC-Ansichtsmuster.Views/Shared is an MVC views pattern. Razor Pages basieren auf der Ordnerhierarchie, nicht auf Pfadkonventionen.Razor Pages are meant to rely on folder hierarchy, not path conventions.

Die Ansichtensuche in einer Razor Page enthält den Ordner Pages.View search from a Razor Page includes the Pages folder. Die Layouts, Vorlagen und Teilansichten, die mit MVC-Controllern und herkömmlichen Razor-Ansichten verwendet werden, funktionieren problemlos.The layouts, templates, and partials used with MVC controllers and conventional Razor views just work.

Fügen Sie eine Datei Pages/_ViewImports.cshtml hinzu:Add a Pages/_ViewImports.cshtml file:

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

@namespace wird weiter unten im Tutorial erläutert.@namespace is explained later in the tutorial. Die @addTagHelper-Anweisung bringt die integrierten Taghilfsprogramme zu allen Seiten in der Ordner Pages.The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

Die @namespace-Anweisung wird wie folgt für eine Seite festgelegt:The @namespace directive set on a page:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

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

Die @namespace-Anweisung legt den Namespace für die Seite fest.The @namespace directive sets the namespace for the page. Die @model-Anweisung muss den Namespace nicht enthalten.The @model directive doesn't need to include the namespace.

Wenn sich die @namespace-Anweisung in _ViewImports.cshtml befindet, stellt der angegebene Namespace das Präfix für den generierten Namespace auf der Seite bereit, die die @namespace-Anweisung importiert.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. Der Rest der generierten Namespaces (der Suffixteil) ist der durch Punkte getrennte relative Pfad zwischen dem Ordner mit _ViewImports.cshtml und dem Ordner, der die Seite enthält.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.

Die PageModel-Klasse in Pages/Customers/Edit.cshtml.cs legt den Namespace z.B. explizit fest: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.

Die Datei Pages/_ViewImports.cshtml legt den folgenden Namespace fest:The Pages/_ViewImports.cshtml file sets the following namespace:

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

Der generierte Namespace für die Razor Page Pages/Customers/Edit.cshtml ist identisch mit der PageModel-Klasse.The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace funktioniert auch mit konventionellen Razor-Ansichten.@namespace also works with conventional Razor views.

Sehen Sie sich die Ansichtsdatei Pages/Create.cshtml an: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>

Die aktualisierte Ansichtsdatei Pages/Create.cshtml mit _ViewImports.cshtml und der vorherigen Layoutdatei sieht wie folgt aus: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>

Im vorangehenden Code werden von _ViewImports.cshtml der Namespace und die Taghilfsprogramme importiert.In the preceding code, the _ViewImports.cshtml imported the namespace and Tag Helpers. Die JavaScript-Dateien werden von der Layoutdatei importiert.The layout file imported the JavaScript files.

Das Razor Pages-Startprojekt enthält die Seite Pages/_ValidationScriptsPartial.cshtml, die die clientseitige Validierung bindet.The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

Weitere Informationen zu Teilansichten finden Sie unter Verwenden von Teilansichten in ASP.NET Core.For more information on partial views, see Verwenden von Teilansichten in ASP.NET Core.

URL-Generierung für SeitenURL generation for Pages

Die zuvor gezeigte Create-Seite verwendet RedirectToPage:The 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");
    }
}

Die App hat die folgende Datei/Ordner-Struktur:The app has the following file/folder structure:

  • /Pages/Pages

    • Index.cshtmlIndex.cshtml

    • Privacy.cshtmlPrivacy.cshtml

    • /Customers/Customers

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

Die Seiten Pages/Customers/Create.cshtml und Pages/Customers/Edit.cshtml führen bei Erfolg eine Umleitung zu Pages/Customers/Index.cshtml durch.The Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Customers/Index.cshtml after success. Die Zeichenfolge ./Index stellt einen relativen Seitennamen dar, der für den Zugriff auf die vorherige Seite verwendet wird.The string ./Index is a relative page name used to access the preceding page. Sie wird für das Generieren von URIs für die Seite Pages/Customers/Index.cshtml verwendet.It is used to generate URLs to the Pages/Customers/Index.cshtml page. Zum Beispiel:For example:

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

Der absolute Seitenname /Index wird zum Generieren der URLs für die Seite Pages/Index.cshtml verwendet.The absolute page name /Index is used to generate URLs to the Pages/Index.cshtml page. Zum Beispiel:For example:

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

Der Seitenname ist der Pfad zu der Seite vom Stammordner /Pages (einschließlich eines vorangestellten /, z.B. /Index).The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). Die oben stehenden Beispiele für eine URL-Generierung bieten erweiterte Optionen und Funktionen, durch die Sie URLs nicht mehr hartcodieren müssen.The preceding URL generation samples offer enhanced options and functional capabilities over hard-coding a URL. Bei der URL-Generierung wird Routing verwendet. Außerdem können damit Parameter generiert und entsprechend der Definition der Route im Zielpfad codiert werden.URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

Die URL-Generierung für Seiten unterstützt relative Namen.URL generation for pages supports relative names. In der folgenden Tabelle wird dargestellt, welche Indexseite durch verschiedene RedirectToPage-Parameter in Pages/Customers/Create.cshtml ausgewählt wird.The following table shows which Index page is selected using different RedirectToPage parameters in Pages/Customers/Create.cshtml.

RedirectToPage(x)RedirectToPage(x) SeitePage
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") und RedirectToPage("../Index") sind relative Namen.RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. Der RedirectToPage-Parameter wird mit dem Pfad der aktuellen Seite kombiniert, um den Namen der Zielseite zu berechnen.The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

Das Verknüpfen relativer Namen eignet sich beim Erstellen von Websites mit einer komplexen Struktur.Relative name linking is useful when building sites with a complex structure. Wenn durch relative Namen Seiten in einem Ordner verknüpft werden, hat das folgende Vorteile:When relative names are used to link between pages in a folder:

  • Relative Links funktionieren weiterhin, wenn ein Ordner umbenannt wird.Renaming a folder doesn't break the relative links.
  • Links funktionieren weiterhin, da sie keinen Ordnernamen enthalten.Links are not broken because they don't include the folder name.

Um auf eine Seite in einem anderen Bereich umzuleiten, geben Sie den Bereich an:To redirect to a page in a different Area, specify the area:

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

Weitere Informationen finden Sie unter Bereiche in ASP.NET Core und Razor Pages: Routen- und App-Konventionen in ASP.NET Core.For more information, see Bereiche in ASP.NET Core and Razor Pages: Routen- und App-Konventionen in ASP.NET Core.

Attribut „ViewData“ViewData attribute

Daten können mit ViewDataAttribute an eine Seite übermittelt werden.Data can be passed to a page with ViewDataAttribute. Für Eigenschaften mit dem [ViewData]-Attribut werden die Werte in ViewDataDictionary gespeichert und daraus geladen.Properties with the [ViewData] attribute have their values stored and loaded from the ViewDataDictionary.

Im folgenden Beispiel wendet AboutModel das [ViewData]-Attribut auf die Title-Eigenschaft an: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()
    {
    }
}

Greifen Sie auf der Infoseite auf die Eigenschaft Title als Modelleigenschaft zu:In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

Im Layout wird der Titel aus dem ViewData-Wörterbuch gelesen: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 macht TempData verfügbar.ASP.NET Core exposes the TempData. Diese Eigenschaft speichert Daten, bis sie gelesen wurden.This property stores data until it's read. Die Methoden Keep und Peek können verwendet werden, um die Daten zu überprüfen, ohne sie zu löschen.The Keep and Peek methods can be used to examine the data without deletion. TempData eignet sich für die Umleitung, wenn Daten für mehr als eine Anforderung benötigt werden.TempData is useful for redirection, when data is needed for more than a single request.

Im folgenden Code wird der Wert von Message mit TempData festgelegt: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");
    }
}

Das folgende Markup in der Datei Pages/Customers/Index.cshtml zeigt den Wert von Message mit TempData an.The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

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

Das Seitenmodell Pages/Customers/Index.cshtml.cs wendet das [TempData]-Attribut auf die Eigenschaft Message an.The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

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

Weitere Informationen finden Sie unter TempData.For more information, see TempData.

Mehrere Handler pro SeiteMultiple handlers per page

Die folgende Seite generiert mit dem asp-page-handler-Taghilfsprogramm Markup für zwei 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>

Das Formular im vorherigen Beispiel hat zwei Sendeschaltflächen, und jede verwendet FormActionTagHelper, um an eine andere URL zu übermitteln.The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. Das asp-page-handler-Attribut ist eine Ergänzung für asp-page.The asp-page-handler attribute is a companion to asp-page. asp-page-handler generiert URLs, die als Übermittlungsziel jeweils die durch eine Seite festgelegte Handlermethode verwenden.asp-page-handler generates URLs that submit to each of the handler methods defined by a page. asp-page wird nicht angegeben, weil das Beispiel mit der aktuellen Seite verknüpft.asp-page isn't specified because the sample is linking to the current page.

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

Der vorherige Code verwendet benannte Handlermethoden.The preceding code uses named handler methods. Benannte Handlermethoden werden aus dem Text im Namen nach On<HTTP Verb> und vor Async (falls vorhanden) erstellt.Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). Im vorherigen Beispiel sind OnPost JoinList Async und OnPost JoinListUC Async die Seitenmethoden.In the preceding example, the page methods are OnPost JoinList Async and OnPost JoinListUC Async. Wenn Sie OnPost und Async entfernen, lauten die Handlernamen JoinList und JoinListUC.With 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" />

Mit dem vorherigen Code lautet der URL-Pfad, der an OnPostJoinListAsync übermittelt, https://localhost:5001/Customers/CreateFATH?handler=JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinList. Der URL-Pfad, der an OnPostJoinListUCAsync übermittelt, lautet https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Benutzerdefinierte RoutenCustom routes

Verwenden Sie die @page-Anweisung für Folgendes:Use the @page directive to:

  • Das Angeben einer benutzerdefinierten Route zu einer Seite.Specify a custom route to a page. Die Route zur Seite „Info“ kann mit @page "/Some/Other/Path" beispielsweise auf /Some/Other/Path festgelegt werden.For example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • Das Anfügen von Segmenten an die Standardroute einer Seite.Append segments to a page's default route. Mit @page "item" kann beispielsweise ein item-Segment an die Standardroute der Seite angefügt werden.For example, an "item" segment can be added to a page's default route with @page "item".
  • Das Anfügen von Parametern an die Standardroute einer Seite.Append parameters to a page's default route. Mit @page "{id}" kann beispielsweise ein ID-Parameter (id) für eine Seite angefordert werden.For example, an ID parameter, id, can be required for a page with @page "{id}".

Es wird ein relativer Pfad zum Stamm unterstützt, der durch eine Tilde (~) festgelegt wird.A root-relative path designated by a tilde (~) at the beginning of the path is supported. @page "~/Some/Other/Path" entspricht beispielsweise @page "/Some/Other/Path".For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

Wenn Sie nicht möchten, dass die Abfragezeichenfolge ?handler=JoinList in der URL enthalten ist, ändern Sie die Route so, dass der Handlername im Pfadteil der URL eingefügt wird.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. Sie können die Route anpassen, indem Sie nach der @page-Anweisung eine Routenvorlage in doppelten Anführungszeichen hinzufügen.The 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>

Mit dem vorherigen Code lautet der URL-Pfad, der an OnPostJoinListAsync übermittelt, https://localhost:5001/Customers/CreateFATH/JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. Der URL-Pfad, der an OnPostJoinListUCAsync übermittelt, lautet https://localhost:5001/Customers/CreateFATH/JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

Das ? nach handler bedeutet, dass der Routenparameter optional ist.The ? following handler means the route parameter is optional.

Erweiterte Konfigurationen und EinstellungenAdvanced configuration and settings

Die Konfigurationen und Einstellungen in den folgenden Abschnitten sind für die meisten Apps nicht erforderlich.The configuration and settings in following sections is not required by most apps.

Verwenden Sie die Überladung AddRazorPages, die RazorPagesOptions konfiguriert, um die erweiterten Optionen zu konfigurieren:To 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");
    });
}

Verwenden Sie RazorPagesOptions, um das Stammverzeichnis für Seiten festzulegen oder Anwendungsmodellkonventionen für Seiten hinzuzufügen.Use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. Weitere Informationen zu Konventionen finden Sie unter Razor Pages-Autorisierungskonventionen.For more information on conventions, see Razor Pages authorization conventions.

Informationen zum Vorkompilieren von Ansichten finden Sie unter Razor-Ansichtenkompilierung.To precompile views, see Razor view compilation.

Festlegen des Inhaltsstammverzeichnisses für Razor PagesSpecify that Razor Pages are at the content root

Standardmäßig lautet das Stammverzeichnis für Razor Pages /Pages.By default, Razor Pages are rooted in the /Pages directory. Fügen Sie WithRazorPagesAtContentRoot hinzu, um anzugeben, dass sich Ihre Razor-Seiten im Inhaltsstammverzeichnis (ContentRootPath) der App befinden: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();
}

Festlegen eines benutzerdefinierten Stammverzeichnisses für Razor PagesSpecify that Razor Pages are at a custom root directory

Fügen Sie WithRazorPagesRoot hinzu, um anzugeben, dass sich Ihre Razor-Seiten in einem benutzerdefinierten Stammverzeichnis der App befinden. Geben Sie dabei einen relativen Pfad an: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");
}

Zusätzliche RessourcenAdditional resources

Warnung

Wenn Sie Visual Studio 2017 verwenden, finden Sie unter dotnet/sdk issue #3124 Informationen zu .NET Core SDK-Versionen, die nicht mit Visual Studio verwendet werden können.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.

Erstellen eines Razor Pages-ProjektsCreate a Razor Pages project

Ausführliche Informationen zum Erstellen eines Razor Pages-Projekts finden Sie unter Erste Schritte mit Razor Pages.See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Razor PagesRazor Pages

Razor Pages ist in Startup.cs aktiviert: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();
    }
}

Sehen Sie sich diese einfache Seite an: Consider a basic page:

@page

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

Der vorherige Code ähnelt sehr einer Razor-Ansichtsdatei, die in einer ASP.NET Core-App mit Controllern und Ansichten verwendet wird.The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. Der Unterschied besteht in der @page-Anweisung.What makes it different is the @page directive. @page macht die Datei zu einer MVC-Aktion, d.h. dass Anfragen direkt ohne einen Controller verarbeitet werden.@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page muss die erste Razor-Anweisung auf einer Seite sein.@page must be the first Razor directive on a page. @page wirkt sich auf das Verhalten aller anderen Razor-Konstrukte aus.@page affects the behavior of other Razor constructs.

Eine ähnliche Seite, die die PageModel-Klasse verwendet, wird in den folgenden zwei Dateien angezeigt.A similar page, using a PageModel class, is shown in the following two files. Die Datei Pages/Index2.cshtml:The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model IndexModel2

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

Das Seitenmodell 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 }";
        }
    }
}

Die PageModel-Klassendatei hat standardmäßig den gleichen Namen wie die Datei mit Razor Pages, nur dass außerdem .cs angefügt wird.By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. Die vorherige Datei mit Razor Razor lautet beispielsweise Pages/Index2.cshtml.For example, the previous Razor Page is Pages/Index2.cshtml. Die Datei mit der PageModel-Klasse heißt Pages/Index2.cshtml.cs.The file containing the PageModel class is named Pages/Index2.cshtml.cs.

Die Zuordnungen von URL-Pfaden zu Seiten werden durch den Speicherort der Seite im Dateisystem bestimmt.The associations of URL paths to pages are determined by the page's location in the file system. Die folgende Tabelle zeigt einen Pfad zu Razor Pages und die entsprechende URL:The following table shows a Razor Page path and the matching URL:

Dateiname und PfadFile name and path Entsprechende URLmatching URL
/Pages/Index.cshtml/Pages/Index.cshtml / oder /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 oder /Store/Index/Store or /Store/Index

Notizen:Notes:

  • Die Runtime sucht standardmäßig im Ordner Pages (Seiten) nach Dateien mit RRazor Pages.The runtime looks for Razor Pages files in the Pages folder by default.
  • Wenn eine Seite nicht in einer URL enthalten ist, ist Index die Standardseite.Index is the default page when a URL doesn't include a page.

Schreiben eines einfachen FormularsWrite a basic form

Razor Pages ist darauf ausgelegt, allgemeine Muster, die mit Webbrowsern verwendet werden können, beim Erstellen einer App leichter implementieren zu können.Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. Die Modellbindung, Taghilfsprogramme und alle HTML-Hilfsprogramme funktionieren nur mit den Eigenschaften, die in einer Klasse der Razor Pages definiert wurden.Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Nehmen wir z.B. eine Seite, die ein allgemeines Kontaktformular für das Contact-Modell implementiert:Consider a page that implements a basic "contact us" form for the Contact model:

Für die Beispiele in diesem Dokument wird DbContext in der Datei Startup.cs initialisiert.For 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();
        }
    }
}

Das Datenmodell: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; }
    }
}

Der db-Kontext: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; }
    }
}

Die Umgebungsdatei 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>

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

Die PageModel -Klasse heißt standardmäßig <PageName>Model und befindet sich im selben Namespace wie die Seite.By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

Mit der Klasse PageModel kann die Logik einer Seite von deren Darstellung getrennt werden.The PageModel class allows separation of the logic of a page from its presentation. Sie definiert Seitenhandler für Anforderungen, die an die Seite geschickt wurden, und für zum Rendern der Seite verwendete Daten.It defines page handlers for requests sent to the page and the data used to render the page. Diese Trennung ermöglicht Folgendes:This separation allows:

Die Seite verfügt über eine OnPostAsync-Handlermethode, die bei POST-Anforderungen ausgeführt wird (wenn ein Benutzer das Formular sendet).The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). Sie können Handlermethoden für alle HTTP-Verben hinzufügen.You can add handler methods for any HTTP verb. Die am häufigsten verwendeten Handler sind:The most common handlers are:

  • OnGet, um den für eine Seite erforderlichen Status zu initialisieren.OnGet to initialize state needed for the page. OnGet-BeispielOnGet sample.
  • OnPost, um Formularübermittlungen zu behandelnOnPost to handle form submissions.

Das Namenssuffix Async ist optional. Es wird jedoch standardmäßig häufig für asynchrone Funktionen verwendet.The Async naming suffix is optional but is often used by convention for asynchronous functions. Der vorhergehende Code ist typisch für Razor Pages.The preceding code is typical for Razor Pages.

Wenn Sie mit ASP.NET-Apps vertraut sind, die Controller und Ansichten verwenden, werden Ihnen folgende Fakten bekannt vorkommen:If you're familiar with ASP.NET apps using controllers and views:

  • Der OnPostAsync-Code im vorangehenden Beispiel ähnelt dem typischen Controllercode.The OnPostAsync code in the preceding example looks similar to typical controller code.
  • Die meisten primitiven MVC-Typen wie solche für Modellbindungen, Validierungen, Validierungen und Aktionsergebnisse werden gemeinsam verwendet.Most of the MVC primitives like model binding, validation, Validation, and action results are shared.

Die vorherige OnPostAsync-Methode:The previous OnPostAsync method:

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

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

Der grundlegende Ablauf von OnPostAsync:The basic flow of OnPostAsync:

Prüfen auf ValidierungsfehlerCheck for validation errors.

  • Wenn keine Fehler vorliegen, werden die Daten gespeichert und weitergeleitet.If there are no errors, save the data and redirect.
  • Wenn es Fehler gibt, zeigen Sie die Seite erneut mit den Validierungsmeldungen an.If there are errors, show the page again with validation messages. Die clientseitige Validierung ist identisch mit herkömmlichen ASP.NET Core MVC-Anwendungen,Client-side validation is identical to traditional ASP.NET Core MVC applications. denn Validierungsfehler werden oftmals auf dem Client erkannt und nie an den Server übermittelt.In many cases, validation errors would be detected on the client, and never submitted to the server.

Wenn die Daten erfolgreich eingegeben wurden, ruft die OnPostAsync-Handlermethode die RedirectToPage-Hilfsmethode auf, um eine Instanz von RedirectToPageResult zurückzugeben.When the data is entered successfully, the OnPostAsync handler method calls the RedirectToPage helper method to return an instance of RedirectToPageResult. RedirectToPage ist ein neues Aktionsergebnis und ähnelt RedirectToAction oder RedirectToRoute, ist aber für Seiten angepasst.RedirectToPage is a new action result, similar to RedirectToAction or RedirectToRoute, but customized for pages. Im vorhergehenden Beispiel leitet es an die Stammindexseite (/Index) weiter.In the preceding sample, it redirects to the root Index page (/Index). Informationen zu RedirectToPage finden Sie im Abschnitt URL-Generierung für Seiten.RedirectToPage is detailed in the URL generation for Pages section.

Wenn das übermittelte Formular Validierungsfehler enthält (die an den Server übergeben wurden), ruft die OnPostAsync-Handlermethode die Page-Hilfsmethode auf.When the submitted form has validation errors (that are passed to the server), theOnPostAsync handler method calls the Page helper method. Page gibt eine Instanz von PageResult zurück.Page returns an instance of PageResult. Der Vorgang, bei dem Page zurückgegeben wird, ähnelt dem Vorgang, bei dem Aktionen im Controller View zurückgeben.Returning Page is similar to how actions in controllers return View. PageResult ist der Standardrückgabetyp für eine Handlermethode.PageResult is the default return type for a handler method. Eine Handlermethode, die void zurückgibt, rendert die Seite.A handler method that returns void renders the page.

Die Eigenschaft Customer verwendet das [BindProperty]-Attribut, um die Modellbindung zu aktivieren.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 Pages binden Eigenschaften standardmäßig nur an Nicht-GET-Verben.Razor Pages, by default, bind properties only with non-GET verbs. Durch die Bindung an Eigenschaften können Sie den Umfang von Codes reduzieren, den Sie schreiben müssen.Binding to properties can reduce the amount of code you have to write. Die Bindung reduziert den Code mithilfe der gleichen Eigenschaft, um Formularfelder (<input asp-for="Customer.Name">) zu rendern und die Eingabe zu akzeptieren.Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

Warnung

Aus Sicherheitsgründen müssen Sie Daten von GET-Anforderungen in die Seitenmodelleigenschaften einbinden.For security reasons, you must opt in to binding GET request data to page model properties. Überprüfen Sie die Benutzereingaben, bevor Sie sie den Eigenschaften zuordnen.Verify user input before mapping it to properties. Die Verwendung der GET-Bindung ist von Vorteil, wenn Sie Szenarios behandeln, die von Abfragezeichenfolgen oder Routenwerten abhängig sind.Opting into GET binding is useful when addressing scenarios that rely on query string or route values.

Legen Sie die SupportsGet-Eigenschaft des [BindProperty]-Attributs auf true fest, um eine Eigenschaft an GET-Anforderungen zu binden:To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Weitere Informationen finden Sie im Video ASP.NET Core Community Standup: Bind on GET discussion (YouTube) (ASP.NET Core Community Standup: Diskussion zur Bindung an GET).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Die Startseite (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>

Die zugeordnete PageModel-Klasse (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();
        }
    }
}

Die Datei Index.cshtml enthält das folgende Markup, um einen Bearbeitungslink für jeden Kontakt zu erstellen: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>

Das Anchor-Taghilfsprogramm <a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> verwendet das asp-route-{value}-Attribut, um einen Link zur Bearbeitungsseite zu generieren.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. Der Link enthält die Routendaten mit der Kontakt-ID.The link contains route data with the contact ID. Beispielsweise https://localhost:5001/Edit/1.For example, https://localhost:5001/Edit/1. Taghilfsprogramme ermöglichen serverseitigem Code das Mitwirken am Erstellen und Rendern von HTML-Elementen in Razor-Dateien.Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. Taghilfsprogramme werden durch @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers aktiviert.Tag Helpers are enabled by @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Die Datei 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>

Die erste Zeile enthält die @page "{id:int}"-Anweisung.The first line contains the @page "{id:int}" directive. Die Routingbeschränkung "{id:int}" weist die Seite an, die Anforderungen für die Seite zu akzeptieren, die int-Routingdaten enthalten.The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. Wenn eine Anforderung an die Seite bestimmte Routingdaten nicht enthält, die in einen int konvertiert werden können, gibt die Runtime einen Fehler vom Typ „HTTP 404: Nicht gefunden“ zurück.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. Um die ID optional zu machen, fügen Sie ? an die Routeneinschränkung an:To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

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

Die Datei index.cshtml enthält auch Markup zum Erstellen der Schaltfläche „Löschen“ für jeden benutzerdefinierten Kontakt: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>

Wenn die „Löschen“-Schaltfläche in HTML gerendert wird, enthält ihr formaction-Element Parameter für Folgendes:When the delete button is rendered in HTML, its formaction includes parameters for:

  • Die benutzerdefinierte Kontakt-ID, die vom asp-route-id-Attribut angegeben wirdThe customer contact ID specified by the asp-route-id attribute.
  • Der handler, der vom asp-page-handler-Attribut angegeben wirdThe handler specified by the asp-page-handler attribute.

Hier sehen Sie ein Beispiel für eine gerenderte „Löschen“-Schaltfläche mit einer benutzerdefinierten Kontakt-ID von 1:Here 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>

Wenn die Schaltfläche ausgewählt wird, wird eine POST-Anforderung an den Server gesendet.When the button is selected, a form POST request is sent to the server. Durch Konvention wird der Name der Handlermethode auf Grundlage des Werts des handler-Parameters gemäß dem Schema OnPost[handler]Async ausgewählt.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.

Da der handler in diesem Beispiel delete ist, wird die Handlermethode OnPostDeleteAsync verwendet, um die POST-Anforderung zu verarbeiten.Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. Wenn asp-page-handler auf einen anderen Wert (z. B. remove) festgelegt wird, wird eine Handlermethode namens OnPostRemoveAsync ausgewählt.If the asp-page-handler is set to a different value, such as remove, a handler method with the name OnPostRemoveAsync is selected. Im folgenden Code wird der OnPostDeleteAsync-Handler definiert: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();
}

Die OnPostDeleteAsync-Methode:The OnPostDeleteAsync method:

  • Akzeptiert die id der Abfragezeichenfolge.Accepts the id from the query string. Wenn die Anweisung der Seite Index.cshtml die Routingeinschränkung "{id:int?}" enthielte, würde id aus den Routendaten abgerufen werden.If the Index.cshtml page directive contained routing constraint "{id:int?}", id would come from route data. Die Routendaten für id werden beispielsweise wie folgt im URI angegeben: https://localhost:5001/Customers/2.The route data for id is specified in the URI such as https://localhost:5001/Customers/2.
  • Fragt mit FindAsync die Datenbank nach dem Kundenkontakt ab.Queries the database for the customer contact with FindAsync.
  • Wenn der Kundenkontakt gefunden wird, wird er aus der Liste der Kundenkontakte entfernt.If the customer contact is found, they're removed from the list of customer contacts. Die Datenbank wurde aktualisiert.The database is updated.
  • Ruft RedirectToPage auf, um die Stammindexseite (/Index) umzuleiten.Calls RedirectToPage to redirect to the root Index page (/Index).

Markieren von Eigenschaften als „Required“ (Erforderlich)Mark page properties as required

Eigenschaften in einem PageModel können mit dem Required-Attribut markiert werden: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");
        }
    }
}

Weitere Informationen finden Sie unter Modellvalidierung.For more information, see Model validation.

Verarbeiten von HEAD-Anforderungen mit einem OnGet-HandlerfallbackHandle HEAD requests with an OnGet handler fallback

HEAD-Anforderungen ermöglichen Ihnen das Abrufen des Headers für eine bestimmte Ressource.HEAD requests allow you to retrieve the headers for a specific resource. Im Gegensatz zu GET-Anforderungen geben HEAD-Anforderungen keinen Antworttext zurück.Unlike GET requests, HEAD requests don't return a response body.

Normalerweise wird ein OnHead-Handler erstellt und für HEAD-Anforderungen aufgerufen:Ordinarily, an OnHead handler is created and called for HEAD requests:

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

In ASP.NET Core 2.1 oder höher greift Razor Pages auf den OnGet-Handler zurück, wenn kein OnHead-Handler definiert ist.In ASP.NET Core 2.1 or later, Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined. Dieses Verhalten wird durch den Aufruf von SetCompatibilityVersion in Startup.ConfigureServices ermöglicht:This behavior is enabled by the call to SetCompatibilityVersion in Startup.ConfigureServices:

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

Die Standardvorlagen generieren den SetCompatibilityVersion-Aufruf in ASP.NET Core 2.1 und 2.2.The default templates generate the SetCompatibilityVersion call in ASP.NET Core 2.1 and 2.2. Tatsächlich legt SetCompatibilityVersion die Razor Pages-Option AllowMappingHeadRequestsToGetHandler auf true fest.SetCompatibilityVersion effectively sets the Razor Pages option AllowMappingHeadRequestsToGetHandler to true.

Sie müssen nicht alle Verhalten in SetCompatibilityVersion aktivieren, sondern können sich nur bestimmte Verhalten aussuchen.Rather than opting in to all behaviors with SetCompatibilityVersion, you can explicitly opt in to specific behaviors. Der folgende Code gibt an, dass HEAD-Anforderungen dem OnGet-Handler zugeordnet werden dürfen: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 und Razor PagesXSRF/CSRF and Razor Pages

Sie müssen keinen Code für die Antifälschungsvalidierung schreiben.You don't have to write any code for antiforgery validation. Die Generierung und Validierung von Antifälschungstoken ist automatisch in Razor Pages enthalten.Antiforgery token generation and validation are automatically included in Razor Pages.

Verwenden von Layouts, Teilansichten, Vorlagen und Taghilfsprogrammen mit Razor PagesUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

Razor Pages beinhaltet alle Funktionen der Razor-Anzeige-Engine.Pages work with all the capabilities of the Razor view engine. Layouts, Teilansichten, Vorlagen, Taghilfsprogramme, _ViewStart.cshtml, _ViewImports.cshtml funktionieren auf die gleiche Weise wie für herkömmliche Razor-Ansichten.Layouts, partials, templates, Tag Helpers, _ViewStart.cshtml, _ViewImports.cshtml work in the same way they do for conventional Razor views.

Strukturieren Sie diese Seite mit einigen dieser praktischen Funktionen.Let's declutter this page by taking advantage of some of those capabilities.

Fügen Sie der Pages/Shared/_Layout.cshtml eine Layoutseite hinzu:Add 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>

Das Layout:The Layout:

  • Steuert das Layout der einzelnen Seiten, es sei denn, das Layout wird für eine Seite deaktiviert.Controls the layout of each page (unless the page opts out of layout).
  • Importiert HTML-Strukturen, z.B. JavaScript und Stylesheets.Imports HTML structures such as JavaScript and stylesheets.

Weitere Informationen finden Sie unter Layoutseite.See layout page for more information.

Die Eigenschaft Layout wird in Pages/_ViewStart.cshtml festgelegt:The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

Das Layout befindet sich im Ordner Pages/Shared.The layout is in the Pages/Shared folder. Seiten suchen hierarchisch nach anderen Ansichten (Layouts, Vorlagen oder Teilansichten) und beginnen im gleichen Ordner wie die aktuelle Seite.Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. Ein Layout im Ordner Pages/Shared kann von jeder Razor-Seite aus unter dem Ordner Pages verwendet werden.A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

Die Layoutdatei sollte im Ordner Pages/Shared gespeichert werden.The layout file should go in the Pages/Shared folder.

Wir empfehlen Ihnen, die Layoutdatei nicht im Ordner Views/Shared (Ansichten/Freigegeben) zu platzieren.We recommend you not put the layout file in the Views/Shared folder. Views/Shared ist ein MVC-Ansichtsmuster.Views/Shared is an MVC views pattern. Razor Pages basieren auf der Ordnerhierarchie, nicht auf Pfadkonventionen.Razor Pages are meant to rely on folder hierarchy, not path conventions.

Die Ansichtensuche in einer Razor Page enthält den Ordner Pages.View search from a Razor Page includes the Pages folder. Die Layouts, Vorlagen und Teilansichten, die Sie mit MVC-Controllern und herkömmlichen Razor-Ansichten verwenden, funktionieren einfach.The layouts, templates, and partials you're using with MVC controllers and conventional Razor views just work.

Fügen Sie eine Datei Pages/_ViewImports.cshtml hinzu:Add a Pages/_ViewImports.cshtml file:

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

@namespace wird weiter unten im Tutorial erläutert.@namespace is explained later in the tutorial. Die @addTagHelper-Anweisung bringt die integrierten Taghilfsprogramme zu allen Seiten in der Ordner Pages.The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

Wenn die @namespace-Anweisung explizit auf eine Seite angewendet wird: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>

Die Anweisung legt den Namespace für die Seite fest.The directive sets the namespace for the page. Die @model-Anweisung muss den Namespace nicht enthalten.The @model directive doesn't need to include the namespace.

Wenn sich die @namespace-Anweisung in _ViewImports.cshtml befindet, stellt der angegebene Namespace das Präfix für den generierten Namespace auf der Seite bereit, die die @namespace-Anweisung importiert.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. Der Rest der generierten Namespaces (der Suffixteil) ist der durch Punkte getrennte relative Pfad zwischen dem Ordner mit _ViewImports.cshtml und dem Ordner, der die Seite enthält.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.

Die PageModel-Klasse in Pages/Customers/Edit.cshtml.cs legt den Namespace z.B. explizit fest: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.

Die Datei Pages/_ViewImports.cshtml legt den folgenden Namespace fest:The Pages/_ViewImports.cshtml file sets the following namespace:

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

Der generierte Namespace für die Razor Page Pages/Customers/Edit.cshtml ist identisch mit der PageModel-Klasse.The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace funktioniert auch mit konventionellen Razor-Ansichten.@namespace also works with conventional Razor views.

Die ursprüngliche Umgebungsdatei 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>

Die aktualisierte Umgebungsdatei 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>

Das Razor Pages-Startprojekt enthält die Seite Pages/_ValidationScriptsPartial.cshtml, die die clientseitige Validierung bindet.The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

Weitere Informationen zu Teilansichten finden Sie unter Verwenden von Teilansichten in ASP.NET Core.For more information on partial views, see Verwenden von Teilansichten in ASP.NET Core.

URL-Generierung für SeitenURL generation for Pages

Die zuvor gezeigte Create-Seite verwendet RedirectToPage:The 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");
}

Die App hat die folgende Datei/Ordner-Struktur:The app has the following file/folder structure:

  • /Pages/Pages

    • Index.cshtmlIndex.cshtml

    • /Customers/Customers

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

Die Seiten Pages/Customers/Create.cshtml und Pages/Customers/Edit.cshtml leiten bei Erfolg an Pages/Index.cshtml weiter.The Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Index.cshtml after success. Die Zeichenfolge /Index ist Teil des URI, der auf die vorhergehende Seite zugreifen soll.The string /Index is part of the URI to access the preceding page. Die Zeichenfolge /Index kann für das Generieren von URIs für die Seite Pages/Index.cshtml verwendet werden.The string /Index can be used to generate URIs to the Pages/Index.cshtml page. Zum Beispiel:For example:

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

Der Seitenname ist der Pfad zu der Seite vom Stammordner /Pages (einschließlich eines vorangestellten /, z.B. /Index).The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). Die oben stehenden Beispiele für eine URL-Generierung bieten erweiterte Optionen und Funktionen, durch die Sie URLs nicht mehr hartcodieren müssen.The preceding URL generation samples offer enhanced options and functional capabilities over hardcoding a URL. Bei der URL-Generierung wird Routing verwendet. Außerdem können damit Parameter generiert und entsprechend der Definition der Route im Zielpfad codiert werden.URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

Die URL-Generierung für Seiten unterstützt relative Namen.URL generation for pages supports relative names. In der folgenden Tabelle wird dargestellt, welche Indexseite für verschiedene RedirectToPage-Parameter aus Pages/Customers/Create.cshtml ausgewählt wird:The following table shows which Index page is selected with different RedirectToPage parameters from Pages/Customers/Create.cshtml:

RedirectToPage(x)RedirectToPage(x) SeitePage
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") und RedirectToPage("../Index") sind relative Namen.RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. Der RedirectToPage-Parameter wird mit dem Pfad der aktuellen Seite kombiniert, um den Namen der Zielseite zu berechnen.The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

Das Verknüpfen relativer Namen eignet sich beim Erstellen von Websites mit einer komplexen Struktur.Relative name linking is useful when building sites with a complex structure. Wenn Sie relative Namen verwenden, um Seiten in einem Ordner zu verknüpfen, können Sie diesen Ordner umbenennen.If you use relative names to link between pages in a folder, you can rename that folder. Alle Links funktionieren weiterhin, da sie nicht den Namen des Ordners enthalten.All the links still work (because they didn't include the folder name).

Um auf eine Seite in einem anderen Bereich umzuleiten, geben Sie den Bereich an:To redirect to a page in a different Area, specify the area:

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

Weitere Informationen finden Sie unter Bereiche in ASP.NET Core.For more information, see Bereiche in ASP.NET Core.

Attribut „ViewData“ViewData attribute

Daten können mit ViewDataAttribute an eine Seite übergeben werden.Data can be passed to a page with ViewDataAttribute. Die Werte der Eigenschaften auf Controllern oder Razor Pages-Modellen, die mit dem [ViewData]-Attribut versehen sind, werden in ViewDataDictionary gespeichert und daraus geladen.Properties on controllers or Razor Page models with the [ViewData] attribute have their values stored and loaded from the ViewDataDictionary.

Im folgenden Beispiel enthält das AboutModel eine Title-Eigenschaft, die mit [ViewData] markiert ist.In the following example, the AboutModel contains a Title property marked with [ViewData]. Die Eigenschaft Title wird auf den Titel der Infoseite festgelegt: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()
    {
    }
}

Greifen Sie auf der Infoseite auf die Eigenschaft Title als Modelleigenschaft zu:In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

Im Layout wird der Titel aus dem ViewData-Wörterbuch gelesen: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 macht die Eigenschaft TempData auf einem Controller verfügbar.ASP.NET Core exposes the TempData property on a controller. Diese Eigenschaft speichert Daten, bis sie gelesen wurden.This property stores data until it's read. Die Methoden Keep und Peek können verwendet werden, um die Daten zu überprüfen, ohne sie zu löschen.The Keep and Peek methods can be used to examine the data without deletion. TempData eignet sich für die Weiterleitung, wenn Daten für mehr als eine Anforderung benötigt werden.TempData is useful for redirection, when data is needed for more than a single request.

Im folgenden Code wird der Wert von Message mit TempData festgelegt: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");
    }
}

Das folgende Markup in der Datei Pages/Customers/Index.cshtml zeigt den Wert von Message mit TempData an.The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

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

Das Seitenmodell Pages/Customers/Index.cshtml.cs wendet das [TempData]-Attribut auf die Eigenschaft Message an.The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

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

Weitere Informationen finden Sie unter TempData.For more information, see TempData .

Mehrere Handler pro SeiteMultiple handlers per page

Die folgende Seite generiert mit dem asp-page-handler-Taghilfsprogramm Markup für zwei 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>

Das Formular im vorherigen Beispiel hat zwei Sendeschaltflächen, und jede verwendet FormActionTagHelper, um an eine andere URL zu übermitteln.The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. Das asp-page-handler-Attribut ist eine Ergänzung für asp-page.The asp-page-handler attribute is a companion to asp-page. asp-page-handler generiert URLs, die als Übermittlungsziel jeweils die durch eine Seite festgelegte Handlermethode verwenden.asp-page-handler generates URLs that submit to each of the handler methods defined by a page. asp-page wird nicht angegeben, weil das Beispiel mit der aktuellen Seite verknüpft.asp-page isn't specified because the sample is linking to the current page.

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

Der vorherige Code verwendet benannte Handlermethoden.The preceding code uses named handler methods. Benannte Handlermethoden werden aus dem Text im Namen nach On<HTTP Verb> und vor Async (falls vorhanden) erstellt.Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). Im vorherigen Beispiel sind OnPost JoinList Async und OnPost JoinListUC Async die Seitenmethoden.In the preceding example, the page methods are OnPost JoinList Async and OnPost JoinListUC Async. Wenn Sie OnPost und Async entfernen, lauten die Handlernamen JoinList und JoinListUC.With 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" />

Mit dem vorherigen Code lautet der URL-Pfad, der an OnPostJoinListAsync übermittelt, https://localhost:5001/Customers/CreateFATH?handler=JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinList. Der URL-Pfad, der an OnPostJoinListUCAsync übermittelt, lautet https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Benutzerdefinierte RoutenCustom routes

Verwenden Sie die @page-Anweisung für Folgendes:Use the @page directive to:

  • Das Angeben einer benutzerdefinierten Route zu einer Seite.Specify a custom route to a page. Die Route zur Seite „Info“ kann mit @page "/Some/Other/Path" beispielsweise auf /Some/Other/Path festgelegt werden.For example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • Das Anfügen von Segmenten an die Standardroute einer Seite.Append segments to a page's default route. Mit @page "item" kann beispielsweise ein item-Segment an die Standardroute der Seite angefügt werden.For example, an "item" segment can be added to a page's default route with @page "item".
  • Das Anfügen von Parametern an die Standardroute einer Seite.Append parameters to a page's default route. Mit @page "{id}" kann beispielsweise ein ID-Parameter (id) für eine Seite angefordert werden.For example, an ID parameter, id, can be required for a page with @page "{id}".

Es wird ein relativer Pfad zum Stamm unterstützt, der durch eine Tilde (~) festgelegt wird.A root-relative path designated by a tilde (~) at the beginning of the path is supported. @page "~/Some/Other/Path" entspricht beispielsweise @page "/Some/Other/Path".For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

Wenn Sie nicht möchten, dass die Abfragezeichenfolge ?handler=JoinList in der URL enthalten ist, ändern Sie die Route so, dass der Handlername im Pfadteil der URL eingefügt wird.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. Sie können die Route anpassen, indem Sie nach der @page-Anweisung eine Routenvorlage in doppelten Anführungszeichen hinzufügen.The 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>

Mit dem vorherigen Code lautet der URL-Pfad, der an OnPostJoinListAsync übermittelt, https://localhost:5001/Customers/CreateFATH/JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. Der URL-Pfad, der an OnPostJoinListUCAsync übermittelt, lautet https://localhost:5001/Customers/CreateFATH/JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

Das ? nach handler bedeutet, dass der Routenparameter optional ist.The ? following handler means the route parameter is optional.

Konfiguration und EinstellungenConfiguration and settings

Um die erweiterten Optionen zu konfigurieren, verwenden Sie die Erweiterungsmethode AddRazorPagesOptions auf dem MVC-Generator:To 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");
        });
}

Derzeit können Sie RazorPagesOptions verwenden, um das Stammverzeichnis für Seiten festzulegen oder Anwendungsmodellkonventionen für Seiten hinzuzufügen.Currently you can use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. Auf diese Weise wird in Zukunft eine höhere Erweiterbarkeit erreicht.We'll enable more extensibility this way in the future.

Informationen zum Vorkompilieren von Ansichten finden Sie unter Razor-Ansichtenkompilierung.To precompile views, see Razor view compilation .

Laden Sie Beispielcode herunter, oder zeigen Sie ihn an.Download or view sample code.

Lesen Sie auch den Artikel Erste Schritte mit Razor Pages, der auf dieser Einführung aufbaut.See Get started with Razor Pages, which builds on this introduction.

Festlegen des Inhaltsstammverzeichnisses für Razor PagesSpecify that Razor Pages are at the content root

Standardmäßig lautet das Stammverzeichnis für Razor Pages /Pages.By default, Razor Pages are rooted in the /Pages directory. Fügen Sie WithRazorPagesAtContentRoot zu AddMvc hinzu, um anzugeben, dass sich Ihre Razor Pages im Inhaltsstammverzeichnis (ContentRootPath) der App befinden:Add WithRazorPagesAtContentRoot to AddMvc to specify that your Razor Pages are at the content root (ContentRootPath) of the app:

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

Festlegen eines benutzerdefinierten Stammverzeichnisses für Razor PagesSpecify that Razor Pages are at a custom root directory

Fügen Sie WithRazorPagesRoot zu AddMvc hinzu, um anzugeben, dass Ihre Razor Pages sich in einem benutzerdefinierten Stammverzeichnis in der App befinden (geben Sie einen relativen Pfad an):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");

Zusätzliche RessourcenAdditional resources