Présentation des pages Razor dans ASP.NET CoreIntroduction to Razor Pages in ASP.NET Core

De Rick Anderson et Ryan NowakBy Rick Anderson and Ryan Nowak

Razor Pages pouvez rendre les scénarios orientés page de codage plus faciles et plus productifs que l’utilisation de contrôleurs et de vues.Razor Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

Si vous cherchez un didacticiel qui utilise l’approche Model-View-Controller, consultez Bien démarrer avec ASP.NET Core MVC.If you're looking for a tutorial that uses the Model-View-Controller approach, see Get started with ASP.NET Core MVC.

Ce document fournit une introduction aux pages Razor.This document provides an introduction to Razor Pages. Il ne s’agit pas d’un didacticiel pas à pas.It's not a step by step tutorial. Si certaines sections vous semblent trop techniques, consultez Bien démarrer avec les pages Razor.If you find some of the sections too advanced, see Get started with Razor Pages. Pour une vue d’ensemble d’ASP.NET Core, consultez Introduction à ASP.NET Core.For an overview of ASP.NET Core, see the Introduction to ASP.NET Core.

Configuration requisePrerequisites

Créer un projet Razor PagesCreate a Razor Pages project

Pour obtenir des instructions sur la création d’un projet Razor Pages, consultez Bien démarrer avec Razor Pages.See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Pages RazorRazor Pages

La fonctionnalité Pages Razor est activée dans Startup.cs :Razor Pages is enabled in Startup.cs:

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

    public IConfiguration Configuration { get; }

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

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

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

        app.UseRouting();

        app.UseAuthorization();

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

Considérez une page de base : Consider a basic page:

@page

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

Le code précédent ressemble beaucoup à un fichier vue Razor utilisé dans une application ASP.NET Core avec des contrôleurs et des vues.The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. Ce qui le rend différent est la directive @page .What makes it different is the @page directive. @page fait du fichier une action MVC, ce qui signifie qu’il gère les demandes directement, sans passer par un contrôleur.@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page doit être la première directive Razor sur une page.@page must be the first Razor directive on a page. @page affecte le comportement d’autres constructions Razor .@page affects the behavior of other Razor constructs. Razor Pages noms de fichiers ont un suffixe . cshtml .Razor Pages file names have a .cshtml suffix.

Une page similaire, utilisant une classe PageModel, est illustrée dans les deux fichiers suivants.A similar page, using a PageModel class, is shown in the following two files. Le fichier Pages/Index2.cshtml :The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model Index2Model

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

Le modèle de page 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 }";
        }
    }
}

Par convention, le fichier de classe PageModel a le même nom que le fichier Page Razor, avec .cs en plus.By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. Par exemple, la page Razor précédente est Pages/Index2.cshtml.For example, the previous Razor Page is Pages/Index2.cshtml. Le fichier contenant la classe PageModel se nomme Pages/Index2.cshtml.cs.The file containing the PageModel class is named Pages/Index2.cshtml.cs.

Les associations des chemins d’URL aux pages sont déterminées par l’emplacement de la page dans le système de fichiers.The associations of URL paths to pages are determined by the page's location in the file system. Le tableau suivant montre un chemin Page Razor et l’URL correspondante :The following table shows a Razor Page path and the matching URL:

Nom et chemin de fichierFile name and path URL correspondantematching URL
/Pages/Index.cshtml/Pages/Index.cshtml / ou /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 ou /Store/Index/Store or /Store/Index

Remarques :Notes:

  • Le runtime recherche les fichiers Pages Razor dans le dossier Pages par défaut.The runtime looks for Razor Pages files in the Pages folder by default.
  • Index est la page par défaut quand une URL n’inclut pas de page.Index is the default page when a URL doesn't include a page.

Écrire un formulaire de baseWrite a basic form

Les pages Razor sont conçues pour que les modèles courants utilisés avec les navigateurs web soient faciles à implémenter lors de la création d’une application.Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. La liaison de modèle, les Tag Helpers et les assistances HTML fonctionnent tous avec les propriétés définies dans une classe Page Razor.Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Considérez une page qui implémente un formulaire « Nous contacter » de base pour le modèle Contact :Consider a page that implements a basic "contact us" form for the Contact model:

Pour les exemples de ce document, le DbContext est initialisé dans le fichier Startup.cs.For the samples in this document, the DbContext is initialized in the Startup.cs file.

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

Le modèle de données :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; }
    }
}

Le contexte de la base de données :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; }
    }
}

Le fichier vue 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>

Le modèle de page 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");
        }
    }
}

Par convention, la classe PageModel se nomme <PageName>Model et se trouve dans le même espace de noms que la page.By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

La classe PageModel permet de séparer la logique d’une page de sa présentation.The PageModel class allows separation of the logic of a page from its presentation. Elle définit des gestionnaires de page pour les demandes envoyées à la page et les données utilisées pour l’afficher.It defines page handlers for requests sent to the page and the data used to render the page. Cette séparation permet :This separation allows:

La page a une méthode de gestionnaire OnPostAsync, qui s’exécute sur les requêtes POST (quand un utilisateur poste le formulaire).The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). Les méthodes de gestionnaire pour tout verbe HTTP peuvent être ajoutées.Handler methods for any HTTP verb can be added. Les gestionnaires les plus courants sont :The most common handlers are:

  • OnGet pour initialiser l’état nécessaire pour la page.OnGet to initialize state needed for the page. Dans le code précédent, la méthode OnGet affiche la page Razor CreateModel. cshtml .In the preceding code, the OnGet method displays the CreateModel.cshtml Razor Page.
  • OnPost pour gérer les envois de formulaire.OnPost to handle form submissions.

Le suffixe de nommage Async est facultatif, mais souvent utilisé par convention pour les fonctions asynchrones.The Async naming suffix is optional but is often used by convention for asynchronous functions. Le code précédent est typique des pages Razor.The preceding code is typical for Razor Pages.

Si vous êtes familiarisé avec les applications ASP.NET à l’aide de contrôleurs et de vues :If you're familiar with ASP.NET apps using controllers and views:

  • Le code OnPostAsync dans l’exemple précédent ressemble au code de contrôleur classique.The OnPostAsync code in the preceding example looks similar to typical controller code.
  • La plupart des primitives MVC, telles que la liaison de modèle, la validationet les résultats d’action, fonctionnent de la même manière avec les contrôleurs et les Razor pages.Most of the MVC primitives like model binding, validation, and action results work the same with Controllers and Razor Pages.

La méthode OnPostAsync précédente :The previous OnPostAsync method:

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

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

    return RedirectToPage("./Index");
}

Le flux de base de OnPostAsync :The basic flow of OnPostAsync:

Recherchez les erreurs de validation.Check for validation errors.

  • S’il n’y a aucune erreur, enregistrez les données et redirigez.If there are no errors, save the data and redirect.
  • S’il y a des erreurs, réaffichez la page avec des messages de validation.If there are errors, show the page again with validation messages. Dans de nombreux cas, les erreurs de validation sont détectées sur le client et jamais envoyées au serveur.In many cases, validation errors would be detected on the client, and never submitted to the server.

Le fichier vue 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>

Le rendu HTML à partir de pages/Create. cshtml: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>

Dans le code précédent, la publication du formulaire :In the previous code, posting the form:

  • Avec des données valides :With valid data:

    • La méthode de gestionnaire OnPostAsync appelle la méthode d’assistance RedirectToPage.The OnPostAsync handler method calls the RedirectToPage helper method. RedirectToPage retourne une instance de RedirectToPageResult.RedirectToPage returns an instance of RedirectToPageResult. RedirectToPage:RedirectToPage:

      • Est un résultat d’action.Is an action result.
      • Est semblable à RedirectToAction ou RedirectToRoute (utilisé dans les contrôleurs et les vues).Is similar to RedirectToAction or RedirectToRoute (used in controllers and views).
      • Est personnalisé pour les pages.Is customized for pages. Dans l’exemple précédent, il redirige vers la page Index racine (/Index).In the preceding sample, it redirects to the root Index page (/Index). RedirectToPage est détaillé dans la section Génération d’URL pour les pages.RedirectToPage is detailed in the URL generation for Pages section.
  • Avec les erreurs de validation qui sont transmises au serveur :With validation errors that are passed to the server:

    • La méthode de gestionnaire OnPostAsync appelle la méthode d’assistance Page.The OnPostAsync handler method calls the Page helper method. Page retourne une instance de PageResult.Page returns an instance of PageResult. Le retour de Page est similaire à la façon dont les actions dans les contrôleurs retournent View.Returning Page is similar to how actions in controllers return View. PageResult est le type de retour par défaut pour une méthode de gestionnaire.PageResult is the default return type for a handler method. Une méthode de gestionnaire qui retourne void restitue la page.A handler method that returns void renders the page.
    • Dans l’exemple précédent, la publication du formulaire sans valeur entraîne le renvoi de la valeur false à ModelState. IsValid .In the preceding example, posting the form with no value results in ModelState.IsValid returning false. Dans cet exemple, aucune erreur de validation n’est affichée sur le client.In this sample, no validation errors are displayed on the client. La gestion des erreurs de validation est traitée plus loin dans ce document.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");
    }
    
  • Avec les erreurs de validation détectées par la validation côté client :With validation errors detected by client side validation:

    • Les données ne sont pas publiées sur le serveur.Data is not posted to the server.
    • La validation côté client est expliquée plus loin dans ce document.Client-side validation is explained later in this document.

La propriété Customer utilise [BindProperty] attribut pour s’abonner à la liaison de modèle :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] ne doit pas être utilisé sur des modèles contenant des propriétés qui ne doivent pas être modifiées par le client.[BindProperty] should not be used on models containing properties that should not be changed by the client. Pour plus d’informations, consultez survalidation.For more information, see Overposting.

Par défaut, Razor Pages lie les propriétés seulement avec des verbes non-GET.Razor Pages, by default, bind properties only with non-GET verbs. La liaison aux propriétés évite d’avoir à écrire du code pour convertir des données HTTP en type de modèle.Binding to properties removes the need to writing code to convert HTTP data to the model type. Elle réduit la quantité de code en utilisant la même propriété pour afficher les champs de formulaire (<input asp-for="Customer.Name">) et accepter l’entrée.Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page.For security reasons, you must opt in to binding GET request data to page model properties. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés.Verify user input before mapping it to properties. L’utilisation de la liaisonestutilelorsdel’adressagedescénariosquireposentsurunechaînederequêteoudesvaleursderoute.GETOpting into GET binding is useful when addressing scenarios that rely on query string or route values.

Pour lier une propriété à GET des demandes, affectez à truela propriété de SupportsGet l’attribut [BindProperty] la valeur :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.net Core Community réunions : Liez sur obtenir une discussion (YouTube).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

Examen du fichier de vue pages/Create. cshtml :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>
  • Dans le code précédent, le tag Helper d’entrée <input asp-for="Customer.Name" /> lie l’élément HTML <input> à l’expression de modèle 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 rend les balises d’aide tag disponibles.@addTagHelper makes Tag Helpers available.

Page d’hébergementThe home page

Index. cshtml est la page d’hébergement :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>
            </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>

La classe PageModel associée (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();
    }
}

Le fichier index. cshtml contient le balisage suivant :The Index.cshtml file contains the following markup:

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

Le <a /a> tag Helper ancre utilisait l’attribut asp-route-{value} pour générer un lien vers la page de modification.The <a /a> Anchor Tag Helper used the asp-route-{value} attribute to generate a link to the Edit page. Le lien contient des données d’itinéraire avec l’ID de contact.The link contains route data with the contact ID. Par exemple, https://localhost:5001/Edit/1.For example, https://localhost:5001/Edit/1. Les Tag Helpers permettent au code côté serveur de participer à la création et au rendu des éléments HTML dans les fichiers Razor.Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.

Le fichier index. cshtml contient un balisage pour créer un bouton Supprimer pour chaque contact client :The Index.cshtml file contains markup to create a delete button for each customer contact:

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

HTML rendu :The rendered HTML:

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

Lorsque le bouton supprimer est rendu en HTML, son formaction comprend des paramètres pour :When the delete button is rendered in HTML, its formaction includes parameters for:

  • ID du contact client, spécifié par l’attribut asp-route-id.The customer contact ID, specified by the asp-route-id attribute.
  • handler, spécifié par l’attribut asp-page-handler.The handler, specified by the asp-page-handler attribute.

Quand le bouton est sélectionné, une demande POST de formulaire est envoyée au serveur.When the button is selected, a form POST request is sent to the server. Par convention, le nom de la méthode de gestionnaire est sélectionné en fonction de la valeur du paramètre handler conformément au schéma OnPost[handler]Async.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.

Étant donné que le handler est delete dans cet exemple, la méthode de gestionnaire OnPostDeleteAsync est utilisée pour traiter la demande POST.Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. Si asp-page-handler est défini sur une autre valeur, comme remove, une méthode de gestionnaire avec le nom OnPostRemoveAsync est sélectionnée.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();
}

La méthode OnPostDeleteAsync :The OnPostDeleteAsync method:

  • Obtient le id à partir de la chaîne de requête.Gets the id from the query string.
  • Interroge la base de données pour le contact client avec FindAsync.Queries the database for the customer contact with FindAsync.
  • Si le contact client est trouvé, il est supprimé et la base de données est mise à jour.If the customer contact is found, it's removed and the database is updated.
  • Appelle RedirectToPage pour rediriger vers la page Index racine (/Index).Calls RedirectToPage to redirect to the root Index page (/Index).

Le fichier Edit. cshtmlThe 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>

La première ligne contient la directive @page "{id:int}".The first line contains the @page "{id:int}" directive. La contrainte de routage "{id:int}" indique à la page qu’elle doit accepter les requêtes qui contiennent des données d’itinéraire int.The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. Si une requête à la page ne contient de données d’itinéraire qui peuvent être converties en int, le runtime retourne une erreur HTTP 404 (introuvable).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. Pour que l’ID soit facultatif, ajoutez ? à la contrainte de route :To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

Le fichier Edit.cshtml.cs :The Edit.cshtml.cs file:

public class EditModel : PageModel
{
    private readonly CustomerDbContext _context;

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

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

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

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

        return Page();
    }

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

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

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

        return RedirectToPage("./Index");
    }

}

ValidationValidation

Règles de validation :Validation rules:

  • Sont spécifiés de façon déclarative dans la classe de modèle.Are declaratively specified in the model class.
  • Sont appliquées partout dans l’application.Are enforced everywhere in the app.

L’espace de noms System.ComponentModel.DataAnnotations fournit un ensemble d’attributs de validation intégrés qui sont appliqués de façon déclarative à une classe ou une propriété.The System.ComponentModel.DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. Le programme DataAnnotations contient également des attributs de mise en forme, comme [DataType] qui facilitent la mise en forme et ne fournissent aucune validation.DataAnnotations also contains formatting attributes like [DataType] that help with formatting and don't provide any validation.

Considérez le modèle de Customer :Consider the Customer model:

using System.ComponentModel.DataAnnotations;

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

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

À l’aide du fichier de vue Create. cshtml suivant :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>

Le code précédent :The preceding code:

  • Comprend des scripts de validation jQuery et jQuery.Includes jQuery and jQuery validation scripts.

  • Utilise les <div /> et <span /> tag helpers pour activer :Uses the <div /> and <span /> Tag Helpers to enable:

    • Validation côté client.Client-side validation.
    • Rendu des erreurs de validation.Validation error rendering.
  • Génère le code HTML suivant :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>
    

La publication de la valeur créer un formulaire sans nom affiche le message d’erreur « le champ nom est obligatoire. »Posting the Create form without a name value displays the error message "The Name field is required." sur le formulaire.on the form. Si JavaScript est activé sur le client, le navigateur affiche l’erreur sans la publier sur le serveur.If JavaScript is enabled on the client, the browser displays the error without posting to the server.

L’attribut [StringLength(10)] génère data-val-length-max="10" sur le rendu HTML.The [StringLength(10)] attribute generates data-val-length-max="10" on the rendered HTML. data-val-length-max empêche les navigateurs d’entrer une valeur supérieure à la longueur maximale spécifiée.data-val-length-max prevents browsers from entering more than the maximum length specified. Si un outil tel que Fiddler est utilisé pour modifier et relire la publication :If a tool such as Fiddler is used to edit and replay the post:

  • Avec le nom plus long que 10.With the name longer than 10.
  • Le message d’erreur « le nom du champ doit être une chaîne d’une longueur maximale de 10 ».The error message "The field Name must be a string with a maximum length of 10." est retourné.is returned.

Considérez le modèle de Movie suivant :Consider the following Movie model:

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""'\s-]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

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

Les attributs de validation spécifient le comportement à appliquer sur les propriétés de modèle auxquelles ils sont appliqués :The validation attributes specify behavior to enforce on the model properties they're applied to:

  • Les attributs Required et MinimumLength indiquent qu’une propriété doit avoir une valeur, mais rien n’empêche un utilisateur d’entrer un espace blanc pour satisfaire cette validation.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.

  • L’attribut RegularExpression sert à limiter les caractères pouvant être entrés.The RegularExpression attribute is used to limit what characters can be input. Dans le code précédent, « Genre » :In the preceding code, "Genre":

    • Doit utiliser seulement des lettres.Must only use letters.
    • La première lettre doit être une majuscule.The first letter is required to be uppercase. Les espaces, les chiffres et les caractères spéciaux ne sont pas autorisés.White space, numbers, and special characters are not allowed.
  • L’expression RegularExpression « Rating » :The RegularExpression "Rating":

    • Nécessite que le premier caractère soit une lettre majuscule.Requires that the first character be an uppercase letter.
    • Autorise les caractères spéciaux et les nombres dans les espaces suivants.Allows special characters and numbers in subsequent spaces. « PG-13 » est valide pour une évaluation, mais échoue pour un « Genre »."PG-13" is valid for a rating, but fails for a "Genre".
  • L’attribut Range contraint une valeur à une plage spécifiée.The Range attribute constrains a value to within a specified range.

  • L’attribut StringLength définit la longueur maximale d’une propriété de type chaîne et, éventuellement, sa longueur minimale.The StringLength attribute sets the maximum length of a string property, and optionally its minimum length.

  • Les types valeur (tels que decimal, int, float et DateTime) sont obligatoires par nature et n’ont pas besoin de l’attribut [Required].Value types (such as decimal, int, float, DateTime) are inherently required and don't need the [Required] attribute.

La page créer du modèle de Movie affiche les erreurs avec des valeurs non valides :The Create page for the Movie model shows displays errors with invalid values:

Formulaire de vue Movie avec plusieurs erreurs de validation jQuery côté client

Pour plus d'informations, voir :For more information, see:

Gérer les requêtes HEAD avec un gestionnaire OnGet de secoursHandle HEAD requests with an OnGet handler fallback

les demandes de HEAD autorisent la récupération des en-têtes pour une ressource spécifique.HEAD requests allow retrieving the headers for a specific resource. Contrairement aux requêtes GET, les requêtes HEAD ne retournent pas un corps de réponse.Unlike GET requests, HEAD requests don't return a response body.

En règle générale, un gestionnaire OnHead est créé et appelé pour les requêtes HEAD :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 revient à appeler le gestionnaire de OnGet si aucun gestionnaire de OnHead n’est défini.Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined.

XSRF/CSRF et pages RazorXSRF/CSRF and Razor Pages

Les Razor Pages sont protégées par la validation anti- contrefaçon.Razor Pages are protected by Antiforgery validation. Le FormTagHelper injecte des jetons anti-contrefaçon dans des éléments de formulaire HTML.The FormTagHelper injects antiforgery tokens into HTML form elements.

Utilisation de dispositions, partiels, modèles et Tag Helpers avec les pages RazorUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

Les pages Razor fonctionnent avec toutes les fonctionnalités du moteur de vue Razor.Pages work with all the capabilities of the Razor view engine. Les dispositions, les parties partielles, les modèles, les tag helpers, _ViewStart. cshtmlet _ViewImports. cshtml fonctionnent de la même façon que pour les vues Razor conventionnelles.Layouts, partials, templates, Tag Helpers, _ViewStart.cshtml, and _ViewImports.cshtml work in the same way they do for conventional Razor views.

Nous allons nettoyer un peu cette page en tirant parti de certaines de ces fonctionnalités.Let's declutter this page by taking advantage of some of those capabilities.

Ajoutez une page de disposition à Pages/Shared/_Layout.cshtml :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>

La disposition :The Layout:

  • Contrôle la disposition de chaque page (à moins que la page ne refuse la disposition).Controls the layout of each page (unless the page opts out of layout).
  • Importe des structures HTML telles que JavaScript et les feuilles de style.Imports HTML structures such as JavaScript and stylesheets.
  • Le contenu de la page Razor est rendu là où @RenderBody() est appelée.The contents of the Razor page are rendered where @RenderBody() is called.

Pour plus d’informations, consultez page disposition.For more information, see layout page.

La propriété Layout est définie dans Pages/_ViewStart.cshtml :The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

La disposition est dans le dossier Pages/Shared.The layout is in the Pages/Shared folder. Les pages recherchent d’autres vues (dispositions, modèles, partiels) hiérarchiquement, en commençant dans le même dossier que la page active.Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. Une disposition dans le dossier Pages/Shared peut être utilisée à partir de n’importe quelle page Razor sous le dossier Pages.A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

Le fichier de disposition doit être placé dans le dossier Pages/Shared.The layout file should go in the Pages/Shared folder.

Nous vous recommandons de ne pas placer le fichier de disposition dans le dossier Views/Shared.We recommend you not put the layout file in the Views/Shared folder. Views/Shared est un modèle de vues MVC.Views/Shared is an MVC views pattern. Les pages Razor sont censées s’appuyer sur la hiérarchie des dossiers, pas sur les conventions de chemins.Razor Pages are meant to rely on folder hierarchy, not path conventions.

La recherche de vue à partir d’une page Razor inclut le dossier Pages.View search from a Razor Page includes the Pages folder. Les dispositions, les modèles et les partiels utilisés avec les contrôleurs MVC et les vues Razor conventionnelles fonctionnent parfaitement.The layouts, templates, and partials used with MVC controllers and conventional Razor views just work.

Ajoutez un fichier Pages/_ViewImports.cshtml :Add a Pages/_ViewImports.cshtml file:

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

@namespace est expliqué plus loin dans le didacticiel.@namespace is explained later in the tutorial. La directive @addTagHelper permet de bénéficier des Tag Helpers intégrés dans toutes les pages du dossier Pages.The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

La directive @namespace définie sur une page :The @namespace directive set on a page:

@page
@namespace RazorPagesIntro.Pages.Customers

@model NameSpaceModel

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

La directive @namespace définit l’espace de noms de la page.The @namespace directive sets the namespace for the page. La directive @model n’a pas besoin d’inclure l’espace de noms.The @model directive doesn't need to include the namespace.

Quand la directive @namespace est contenue dans _ViewImports.cshtml, l’espace de noms spécifié fournit le préfixe de l’espace de noms généré dans la Page qui importe la directive @namespace.When the @namespace directive is contained in _ViewImports.cshtml, the specified namespace supplies the prefix for the generated namespace in the Page that imports the @namespace directive. Le reste de l’espace de noms généré (la partie suffixe) est le chemin relatif séparé par un point entre le dossier contenant _ViewImports.cshtml et le dossier contenant la page.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.

Par exemple, la classe PageModel Pages/Customers/Edit.cshtml.cs définit explicitement l’espace de noms :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.

Le fichier Pages/_ViewImports.cshtml définit l’espace de noms suivant :The Pages/_ViewImports.cshtml file sets the following namespace:

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

L’espace de noms généré pour la page Razor Pages/Customers/Edit.cshtml est identique à la classe PageModel.The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace fonctionne également avec les vues Razor classiques.@namespace also works with conventional Razor views.

Examinez le fichier de vue pages/Create. cshtml :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>

Le fichier de vue pages/Create. cshtml mis à jour avec _ViewImports. cshtml et le fichier de disposition précédent :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>

Dans le code précédent, _ViewImports. cshtml a importé l’espace de noms et les tag helpers.In the preceding code, the _ViewImports.cshtml imported the namespace and Tag Helpers. Le fichier de disposition a importé les fichiers JavaScript.The layout file imported the JavaScript files.

Le projet de démarrage de pages Razor contient Pages/_ValidationScriptsPartial.cshtml, qui connecte la validation côté client.The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

Pour plus d'informations sur les affichages partiels, consultez Vues partielles dans ASP.NET Core.For more information on partial views, see Vues partielles dans ASP.NET Core.

Génération d’URL pour les pagesURL generation for Pages

La page Create, illustrée précédemment, utilise 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");
    }
}

L’application a la structure de fichiers/dossiers suivante :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

Les pages pages/Customers/Create. cshtml et pages/Customers/Edit. cshtml redirigent vers pages/Customers/index. cshtml après réussite.The Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Customers/Index.cshtml after success. La chaîne ./Index est un nom de page relatif utilisé pour accéder à la page précédente.The string ./Index is a relative page name used to access the preceding page. Elle est utilisée pour générer des URL dans la page pages/Customers/index. cshtml .It is used to generate URLs to the Pages/Customers/Index.cshtml page. Exemple :For example:

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

Le nom de page absolu /Index est utilisé pour générer des URL dans la page pages/index. cshtml .The absolute page name /Index is used to generate URLs to the Pages/Index.cshtml page. Exemple :For example:

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

Le nom de la page est le chemin de la page à partir du dossier racine /Pages avec un / devant (par exemple, /Index).The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). Les exemples de génération d’URL précédents offrent des options améliorées et des fonctionnalités fonctionnelles par rapport au codage en dur d’une URL.The preceding URL generation samples offer enhanced options and functional capabilities over hard-coding a URL. La génération d’URL utilise le routage et peut générer et encoder des paramètres en fonction de la façon dont l’itinéraire est défini dans le chemin de destination.URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

La génération d’URL pour les pages prend en charge les noms relatifs.URL generation for pages supports relative names. Le tableau suivant indique quelle page d’index est sélectionnée à l’aide de différents paramètres de RedirectToPage dans pages/Customers/Create. cshtml.The following table shows which Index page is selected using different RedirectToPage parameters in Pages/Customers/Create.cshtml.

RedirectToPage(x)RedirectToPage(x) PagePage
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")et RedirectToPage("../Index") sont des noms relatifs.RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. Le paramètre RedirectToPage est combiné avec le chemin de la page active pour calculer le nom de la page de destination.The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

La liaison de nom relatif est utile lors de la création de sites avec une structure complexe.Relative name linking is useful when building sites with a complex structure. Lorsque des noms relatifs sont utilisés pour établir une liaison entre les pages d’un dossier :When relative names are used to link between pages in a folder:

  • Le changement de nom d’un dossier n’interrompt pas les liens relatifs.Renaming a folder doesn't break the relative links.
  • Les liens ne sont pas rompus, car ils n’incluent pas le nom du dossier.Links are not broken because they don't include the folder name.

Pour rediriger vers une page située dans une autre Zone, spécifiez la zone :To redirect to a page in a different Area, specify the area:

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

Pour plus d’informations, consultez Zones dans ASP.NET Core et Conventions de routes et d’applications pour les pages Razor dans ASP.NET Core.For more information, see Zones dans ASP.NET Core and Conventions de routes et d’applications pour les pages Razor dans ASP.NET Core.

Attribut ViewDataViewData attribute

Les données peuvent être passées à une page avec ViewDataAttribute.Data can be passed to a page with ViewDataAttribute. Les valeurs des propriétés avec l’attribut [ViewData] sont stockées et chargées à partir du ViewDataDictionary.Properties with the [ViewData] attribute have their values stored and loaded from the ViewDataDictionary.

Dans l’exemple suivant, le AboutModel applique l’attribut [ViewData] à la propriété Title :In the following example, the AboutModel applies the [ViewData] attribute to the Title property:

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

    public void OnGet()
    {
    }
}

Dans la page À propos de, accédez à la propriété Title en tant que propriété de modèle :In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

Dans la disposition, le titre est lu à partir du dictionnaire ViewData :In the layout, the title is read from the ViewData dictionary:

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

TempDataTempData

ASP.NET Core expose le TempData.ASP.NET Core exposes the TempData. Cette propriété stocke les données jusqu’à ce qu’elles soient lues.This property stores data until it's read. Vous pouvez utiliser les méthodes Keep et Peek pour examiner les données sans suppression.The Keep and Peek methods can be used to examine the data without deletion. TempData est utile pour la redirection, lorsque les données sont nécessaires pour plusieurs requêtes.TempData is useful for redirection, when data is needed for more than a single request.

Le code suivant définit la valeur de Message à l’aide de TempData :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");
    }
}

Le balisage suivant dans le fichier Pages/Customers/Index.cshtml affiche la valeur de Message à l’aide de TempData.The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

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

Le modèle de page Pages/Customers/Index.cshtml.cs applique l’attribut [TempData] à la propriété Message.The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

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

Pour plus d’informations, consultez TempData.For more information, see TempData.

Plusieurs gestionnaires par pageMultiple handlers per page

La page suivante génère un balisage pour deux gestionnaires en utilisant le Tag Helper asp-page-handler :The following page generates markup for two handlers using the asp-page-handler Tag Helper:

@page
@model CreateFATHModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div>Name: <input asp-for="Customer.Name" /></div>
        <input type="submit" asp-page-handler="JoinList" value="Join" />
        <input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
    </form>
</body>
</html>

Le formulaire dans l’exemple précédent contient deux boutons d’envoi, chacun utilisant FormActionTagHelper pour envoyer à une URL différente.The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. L’attribut asp-page-handler est un complément de asp-page.The asp-page-handler attribute is a companion to asp-page. asp-page-handler génère des URL qui envoient à chacune des méthodes de gestionnaire définies par une page.asp-page-handler generates URLs that submit to each of the handler methods defined by a page. asp-page n’est pas spécifié, car l’exemple établit une liaison à la page active.asp-page isn't specified because the sample is linking to the current page.

Le modèle de page :The page model:

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

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

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

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

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

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

        public async Task<IActionResult> OnPostJoinListUCAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            Customer.Name = Customer.Name?.ToUpper();
            return await OnPostJoinListAsync();
        }
    }
}

Le code précédent utilise des méthodes de gestionnaire nommées.The preceding code uses named handler methods. Pour créer des méthodes de gestionnaire nommées, il faut prendre le texte dans le nom après On<HTTP Verb> et avant Async (le cas échéant).Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). Dans l’exemple précédent, les méthodes de page sont OnPostJoinListAsync et OnPostJoinListUCAsync.In the preceding example, the page methods are OnPostJoinListAsync and OnPostJoinListUCAsync. Avec OnPost et Async supprimés, les noms des gestionnaires sont JoinList et 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" />

Avec le code précédent, le chemin d’URL qui envoie à OnPostJoinListAsync est 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. Le chemin d’URL qui envoie à OnPostJoinListUCAsync est https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Routes personnaliséesCustom routes

Utilisez la directive @page pour :Use the @page directive to:

  • Spécifier une route personnalisée vers une page.Specify a custom route to a page. Par exemple, la route vers la page À propos peut être définie sur /Some/Other/Path avec @page "/Some/Other/Path".For example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • Ajouter des segments à la route par défaut d’une page.Append segments to a page's default route. Par exemple, un segment « item » peut être ajouté à la route par défaut d’une page avec @page "item".For example, an "item" segment can be added to a page's default route with @page "item".
  • Ajouter des paramètres à la route par défaut d’une page.Append parameters to a page's default route. Par exemple, un paramètre d’ID, id, peut être nécessaire pour une page avec @page "{id}".For example, an ID parameter, id, can be required for a page with @page "{id}".

Un chemin relatif racine désigné par un tilde (~) au début du chemin est pris en charge.A root-relative path designated by a tilde (~) at the beginning of the path is supported. Par exemple, @page "~/Some/Other/Path" est identique à @page "/Some/Other/Path".For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

Vous pouvez remplacer la chaîne de requête ?handler=JoinList dans l’URL par un segment de routage /JoinList en spécifiant le modèle de routage @page "{handler?}".You can change the query string ?handler=JoinList in the URL to a route segment /JoinList by specifying the route template @page "{handler?}".

Si vous ne voulez pas avoir la chaîne de requête ?handler=JoinList dans l’URL, vous pouvez changer l’itinéraire pour placer le nom du gestionnaire dans la partie chemin de l’URL.If you don't like the query string ?handler=JoinList in the URL, you can change the route to put the handler name in the path portion of the URL. Vous pouvez personnaliser l’itinéraire en ajoutant un modèle d’itinéraire placé entre des guillemets doubles après la directive @page.You can customize the route 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>

Avec le code précédent, le chemin d’URL qui envoie à OnPostJoinListAsync est https://localhost:5001/Customers/CreateFATH/JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. Le chemin d’URL qui envoie à OnPostJoinListUCAsync est https://localhost:5001/Customers/CreateFATH/JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

Le ? suivant handler signifie que le paramètre d’itinéraire est facultatif.The ? following handler means the route parameter is optional.

Configuration et paramètres avancésAdvanced configuration and settings

La configuration et les paramètres des sections suivantes ne sont pas requis par la plupart des applications.The configuration and settings in following sections is not required by most apps.

Pour configurer des options avancées, utilisez la méthode d’extension AddRazorPagesOptions:To configure advanced options, use the extension method AddRazorPagesOptions:

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

Utilisez la RazorPagesOptions pour définir le répertoire racine des pages ou ajouter des conventions de modèle d’application pour les pages.Use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. Pour plus d’informations sur les conventions, consultez Razor pages conventions d’autorisation.For more information on conventions, see Razor Pages authorization conventions.

Pour précompiler des vues, consultez compilation de vue Razor.To precompile views, see Razor view compilation.

Spécifier que les pages Razor se trouvent à la racine du contenuSpecify that Razor Pages are at the content root

Par défaut, les pages Razor sont associées à la racine /Pages.By default, Razor Pages are rooted in the /Pages directory. Ajoutez WithRazorPagesAtContentRoot pour spécifier que votre Razor Pages se trouve à la racine du contenu (ContentRootPath) de l’application :Add WithRazorPagesAtContentRoot to specify that your Razor Pages are at the content root (ContentRootPath) of the app:

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

Spécifier que les pages Razor se trouvent dans un répertoire racine personnaliséSpecify that Razor Pages are at a custom root directory

Ajoutez WithRazorPagesRoot pour spécifier que les Razor Pages se trouvent dans un répertoire racine personnalisé dans l’application (fournissez un chemin d’accès relatif) :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()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.AuthorizeFolder("/MyPages/Admin");
        })
        .WithRazorPagesRoot("/path/to/razor/pages");
}

Ressources supplémentairesAdditional resources

De Rick Anderson et Ryan NowakBy Rick Anderson and Ryan Nowak

Les pages Razor constituent un nouvel aspect d’ASP.NET Core MVC qui permet de développer des scénarios orientés page de façon plus simple et plus productive.Razor Pages is a new aspect of ASP.NET Core MVC that makes coding page-focused scenarios easier and more productive.

Si vous cherchez un didacticiel qui utilise l’approche Model-View-Controller, consultez Bien démarrer avec ASP.NET Core MVC.If you're looking for a tutorial that uses the Model-View-Controller approach, see Get started with ASP.NET Core MVC.

Ce document fournit une introduction aux pages Razor.This document provides an introduction to Razor Pages. Il ne s’agit pas d’un didacticiel pas à pas.It's not a step by step tutorial. Si certaines sections vous semblent trop techniques, consultez Bien démarrer avec les pages Razor.If you find some of the sections too advanced, see Get started with Razor Pages. Pour une vue d’ensemble d’ASP.NET Core, consultez Introduction à ASP.NET Core.For an overview of ASP.NET Core, see the Introduction to ASP.NET Core.

Configuration requisePrerequisites

Avertissement

Si vous utilisez Visual Studio 2017, consultez le problème no 3124 dotnet/sdk pour plus d’informations sur les versions du Kit SDK .NET Core qui ne fonctionnent pas avec Visual Studio.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.

Créer un projet Razor PagesCreate a Razor Pages project

Pour obtenir des instructions sur la création d’un projet Razor Pages, consultez Bien démarrer avec Razor Pages.See Get started with Razor Pages for detailed instructions on how to create a Razor Pages project.

Pages RazorRazor Pages

La fonctionnalité Pages Razor est activée dans Startup.cs :Razor Pages is enabled in Startup.cs:

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

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

Considérez une page de base : Consider a basic page:

@page

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

Le code précédent ressemble beaucoup à un fichier vue Razor utilisé dans une application ASP.NET Core avec des contrôleurs et des vues.The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. Ce qui le rend différent est la directive @page.What makes it different is the @page directive. @page fait du fichier une action MVC, ce qui signifie qu’il gère les demandes directement, sans passer par un contrôleur.@page makes the file into an MVC action - which means that it handles requests directly, without going through a controller. @page doit être la première directive Razor sur une page.@page must be the first Razor directive on a page. @page affecte le comportement d’autres constructions Razor.@page affects the behavior of other Razor constructs.

Une page similaire, utilisant une classe PageModel, est illustrée dans les deux fichiers suivants.A similar page, using a PageModel class, is shown in the following two files. Le fichier Pages/Index2.cshtml :The Pages/Index2.cshtml file:

@page
@using RazorPagesIntro.Pages
@model IndexModel2

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

Le modèle de page 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 }";
        }
    }
}

Par convention, le fichier de classe PageModel a le même nom que le fichier Page Razor, avec .cs en plus.By convention, the PageModel class file has the same name as the Razor Page file with .cs appended. Par exemple, la page Razor précédente est Pages/Index2.cshtml.For example, the previous Razor Page is Pages/Index2.cshtml. Le fichier contenant la classe PageModel se nomme Pages/Index2.cshtml.cs.The file containing the PageModel class is named Pages/Index2.cshtml.cs.

Les associations des chemins d’URL aux pages sont déterminées par l’emplacement de la page dans le système de fichiers.The associations of URL paths to pages are determined by the page's location in the file system. Le tableau suivant montre un chemin Page Razor et l’URL correspondante :The following table shows a Razor Page path and the matching URL:

Nom et chemin de fichierFile name and path URL correspondantematching URL
/Pages/Index.cshtml/Pages/Index.cshtml / ou /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 ou /Store/Index/Store or /Store/Index

Remarques :Notes:

  • Le runtime recherche les fichiers Pages Razor dans le dossier Pages par défaut.The runtime looks for Razor Pages files in the Pages folder by default.
  • Index est la page par défaut quand une URL n’inclut pas de page.Index is the default page when a URL doesn't include a page.

Écrire un formulaire de baseWrite a basic form

Les pages Razor sont conçues pour que les modèles courants utilisés avec les navigateurs web soient faciles à implémenter lors de la création d’une application.Razor Pages is designed to make common patterns used with web browsers easy to implement when building an app. La liaison de modèle, les Tag Helpers et les assistances HTML fonctionnent tous avec les propriétés définies dans une classe Page Razor.Model binding, Tag Helpers, and HTML helpers all just work with the properties defined in a Razor Page class. Considérez une page qui implémente un formulaire « Nous contacter » de base pour le modèle Contact :Consider a page that implements a basic "contact us" form for the Contact model:

Pour les exemples de ce document, le DbContext est initialisé dans le fichier Startup.cs.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();
        }
    }
}

Le modèle de données :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; }
    }
}

Le contexte de la base de données :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; }
    }
}

Le fichier vue 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>

Le modèle de page 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");
        }
    }
}

Par convention, la classe PageModel se nomme <PageName>Model et se trouve dans le même espace de noms que la page.By convention, the PageModel class is called <PageName>Model and is in the same namespace as the page.

La classe PageModel permet de séparer la logique d’une page de sa présentation.The PageModel class allows separation of the logic of a page from its presentation. Elle définit des gestionnaires de page pour les demandes envoyées à la page et les données utilisées pour l’afficher.It defines page handlers for requests sent to the page and the data used to render the page. Cette séparation permet :This separation allows:

La page a une méthode de gestionnaire OnPostAsync, qui s’exécute sur les requêtes POST (quand un utilisateur poste le formulaire).The page has an OnPostAsync handler method, which runs on POST requests (when a user posts the form). Vous pouvez ajouter des méthodes de gestionnaire pour n’importe quel verbe HTTP.You can add handler methods for any HTTP verb. Les gestionnaires les plus courants sont :The most common handlers are:

  • OnGet pour initialiser l’état nécessaire pour la page.OnGet to initialize state needed for the page. Exemple OnGet.OnGet sample.
  • OnPost pour gérer les envois de formulaire.OnPost to handle form submissions.

Le suffixe de nommage Async est facultatif, mais souvent utilisé par convention pour les fonctions asynchrones.The Async naming suffix is optional but is often used by convention for asynchronous functions. Le code précédent est typique des pages Razor.The preceding code is typical for Razor Pages.

Si vous êtes familiarisé avec les applications ASP.NET à l’aide de contrôleurs et de vues :If you're familiar with ASP.NET apps using controllers and views:

  • Le code OnPostAsync dans l’exemple précédent ressemble au code de contrôleur classique.The OnPostAsync code in the preceding example looks similar to typical controller code.
  • La plupart des primitives MVC, telles que la liaison de modèle, la validation, la validationet les résultats d’action, sont partagées.Most of the MVC primitives like model binding, validation, Validation, and action results are shared.

La méthode OnPostAsync précédente :The previous OnPostAsync method:

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

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

Le flux de base de OnPostAsync :The basic flow of OnPostAsync:

Recherchez les erreurs de validation.Check for validation errors.

  • S’il n’y a aucune erreur, enregistrez les données et redirigez.If there are no errors, save the data and redirect.
  • S’il y a des erreurs, réaffichez la page avec des messages de validation.If there are errors, show the page again with validation messages. La validation côté client est identique à celle des applications ASP.NET Core MVC traditionnelles.Client-side validation is identical to traditional ASP.NET Core MVC applications. Dans de nombreux cas, les erreurs de validation sont détectées sur le client et jamais envoyées au serveur.In many cases, validation errors would be detected on the client, and never submitted to the server.

Quand les données sont entrées correctement, la méthode de gestionnaire OnPostAsync appelle la méthode d’assistance RedirectToPage pour retourner une instance de RedirectToPageResult.When the data is entered successfully, the OnPostAsync handler method calls the RedirectToPage helper method to return an instance of RedirectToPageResult. RedirectToPage est un nouveau résultat d’action, semblable à RedirectToAction ou RedirectToRoute, mais personnalisé pour les pages.RedirectToPage is a new action result, similar to RedirectToAction or RedirectToRoute, but customized for pages. Dans l’exemple précédent, il redirige vers la page Index racine (/Index).In the preceding sample, it redirects to the root Index page (/Index). RedirectToPage est détaillé dans la section Génération d’URL pour les pages.RedirectToPage is detailed in the URL generation for Pages section.

Quand le formulaire envoyé comporte des erreurs de validation (qui sont passées au serveur), la méthode de gestionnaire OnPostAsync appelle la méthode d’assistance Page.When the submitted form has validation errors (that are passed to the server), theOnPostAsync handler method calls the Page helper method. Page retourne une instance de PageResult.Page returns an instance of PageResult. Le retour de Page est similaire à la façon dont les actions dans les contrôleurs retournent View.Returning Page is similar to how actions in controllers return View. PageResult est le type de retour par défaut pour une méthode de gestionnaire.PageResult is the default return type for a handler method. Une méthode de gestionnaire qui retourne void restitue la page.A handler method that returns void renders the page.

La propriété Customer utilise l’attribut [BindProperty] pour accepter la liaison de modèle.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");
    }
}

Par défaut, Razor Pages lie les propriétés seulement avec des verbes non-GET.Razor Pages, by default, bind properties only with non-GET verbs. La liaison aux propriétés peut réduire la quantité de code à écrire.Binding to properties can reduce the amount of code you have to write. Elle réduit la quantité de code en utilisant la même propriété pour afficher les champs de formulaire (<input asp-for="Customer.Name">) et accepter l’entrée.Binding reduces code by using the same property to render form fields (<input asp-for="Customer.Name">) and accept the input.

Avertissement

Pour des raisons de sécurité, vous devez choisir de lier les données de requête GET aux propriétés du modèle de page.For security reasons, you must opt in to binding GET request data to page model properties. Vérifiez l’entrée utilisateur avant de la mapper à des propriétés.Verify user input before mapping it to properties. L’utilisation de la liaisonestutilelorsdel’adressagedescénariosquireposentsurunechaînederequêteoudesvaleursderoute.GETOpting into GET binding is useful when addressing scenarios that rely on query string or route values.

Pour lier une propriété à GET des demandes, affectez à truela propriété de SupportsGet l’attribut [BindProperty] la valeur :To bind a property on GET requests, set the [BindProperty] attribute's SupportsGet property to true:

[BindProperty(SupportsGet = true)]

Pour plus d’informations, consultez ASP.net Core Community réunions : Liez sur obtenir une discussion (YouTube).For more information, see ASP.NET Core Community Standup: Bind on GET discussion (YouTube).

La page d’accueil (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>

La classe PageModel associée (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();
        }
    }
}

Le fichier Index.cshtml contient le balisage suivant pour créer un lien d’édition pour chaque contact :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>

Le <a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> tag Helper ancre utilisait l’attribut asp-route-{value} pour générer un lien vers la page de modification.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. Le lien contient des données d’itinéraire avec l’ID de contact.The link contains route data with the contact ID. Par exemple, https://localhost:5001/Edit/1.For example, https://localhost:5001/Edit/1. Les Tag Helpers permettent au code côté serveur de participer à la création et au rendu des éléments HTML dans les fichiers Razor.Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files. Les tag helpers sont activés par @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpersTag Helpers are enabled by @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Le fichier 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>

La première ligne contient la directive @page "{id:int}".The first line contains the @page "{id:int}" directive. La contrainte de routage "{id:int}" indique à la page qu’elle doit accepter les requêtes qui contiennent des données d’itinéraire int.The routing constraint"{id:int}" tells the page to accept requests to the page that contain int route data. Si une requête à la page ne contient de données d’itinéraire qui peuvent être converties en int, le runtime retourne une erreur HTTP 404 (introuvable).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. Pour que l’ID soit facultatif, ajoutez ? à la contrainte de route :To make the ID optional, append ? to the route constraint:

@page "{id:int?}"

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

Le fichier Index.cshtml contient également le balisage pour créer un bouton Supprimer pour chaque contact client :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>

Lorsque le bouton Supprimer est rendu en HTML, son formaction comprend des paramètres pour :When the delete button is rendered in HTML, its formaction includes parameters for:

  • L’ID du contact client spécifié par l’attribut asp-route-id.The customer contact ID specified by the asp-route-id attribute.
  • Le handler spécifié par l’attribut asp-page-handler.The handler specified by the asp-page-handler attribute.

Voici un exemple de bouton Supprimer rendu avec un ID de contact client de 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>

Quand le bouton est sélectionné, une demande POST de formulaire est envoyée au serveur.When the button is selected, a form POST request is sent to the server. Par convention, le nom de la méthode de gestionnaire est sélectionné en fonction de la valeur du paramètre handler conformément au schéma OnPost[handler]Async.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.

Étant donné que le handler est delete dans cet exemple, la méthode de gestionnaire OnPostDeleteAsync est utilisée pour traiter la demande POST.Because the handler is delete in this example, the OnPostDeleteAsync handler method is used to process the POST request. Si asp-page-handler est défini sur une autre valeur, comme remove, une méthode de gestionnaire avec le nom OnPostRemoveAsync est sélectionnée.If the asp-page-handler is set to a different value, such as remove, a handler method with the name OnPostRemoveAsync is selected. Le code suivant montre le gestionnaire de OnPostDeleteAsync :The following code shows the OnPostDeleteAsync handler:

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

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

    return RedirectToPage();
}

La méthode OnPostDeleteAsync :The OnPostDeleteAsync method:

  • Accepte l’id de la chaîne de requête.Accepts the id from the query string. Si la directive de la page index. cshtml contient des "{id:int?}"de contrainte de routage, id provient des données d’itinéraire.If the Index.cshtml page directive contained routing constraint "{id:int?}", id would come from route data. Les données d’itinéraire pour id sont spécifiées dans l’URI, par exemple https://localhost:5001/Customers/2.The route data for id is specified in the URI such as https://localhost:5001/Customers/2.
  • Interroge la base de données pour le contact client avec FindAsync.Queries the database for the customer contact with FindAsync.
  • Si le contact client est trouvé, il est supprimé de la liste des contacts client.If the customer contact is found, they're removed from the list of customer contacts. La base de données est mise à jour.The database is updated.
  • Appelle RedirectToPage pour rediriger vers la page Index racine (/Index).Calls RedirectToPage to redirect to the root Index page (/Index).

Marquer les propriétés de page comme RequiredMark page properties as required

Les propriétés définies sur PageModel peuvent être décorées avec l’attribut Required :Properties on a PageModel can be decorated 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");
        }
    }
}

Pour plus d’informations, consultez Validation de modèle.For more information, see Model validation.

Gérer les requêtes HEAD avec un gestionnaire OnGet de secoursHandle HEAD requests with an OnGet handler fallback

Les requêtes HEAD vous permettent de récupérer les en-têtes pour une ressource spécifique.HEAD requests allow you to retrieve the headers for a specific resource. Contrairement aux requêtes GET, les requêtes HEAD ne retournent pas un corps de réponse.Unlike GET requests, HEAD requests don't return a response body.

En règle générale, un gestionnaire OnHead est créé et appelé pour les requêtes HEAD :Ordinarily, an OnHead handler is created and called for HEAD requests:

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

Dans ASP.NET Core 2.1 ou ultérieur, Razor Pages se rabat sur un appel du gestionnaire OnGet si aucun gestionnaire OnHead n’est défini.In ASP.NET Core 2.1 or later, Razor Pages falls back to calling the OnGet handler if no OnHead handler is defined. Ce comportement est activé par l’appel à SetCompatibilityVersion dans Startup.ConfigureServices :This behavior is enabled by the call to SetCompatibilityVersion in Startup.ConfigureServices:

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

Les modèles par défaut génèrent l'appel SetCompatibilityVersion dans ASP.NET Core 2.1 et 2.2.The default templates generate the SetCompatibilityVersion call in ASP.NET Core 2.1 and 2.2. SetCompatibilityVersion définit efficacement l’option Pages Razor AllowMappingHeadRequestsToGetHandler sur true.SetCompatibilityVersion effectively sets the Razor Pages option AllowMappingHeadRequestsToGetHandler to true.

Au lieu d’adhérer à tous les comportements avec SetCompatibilityVersion, vous pouvez adhérer explicitement à des comportements spécifiques.Rather than opting in to all behaviors with SetCompatibilityVersion, you can explicitly opt in to specific behaviors. Le code suivant adhère à l’autorisation de mappage des requêtes HEAD au gestionnaire OnGet :The following code opts in to allowing HEAD requests to be mapped to the OnGet handler:

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

XSRF/CSRF et pages RazorXSRF/CSRF and Razor Pages

Vous n’avez aucun code à écrire pour la validation anti-contrefaçon.You don't have to write any code for antiforgery validation. La validation et la génération de jetons anti-contrefaçon sont automatiquement incluses dans les pages Razor.Antiforgery token generation and validation are automatically included in Razor Pages.

Utilisation de dispositions, partiels, modèles et Tag Helpers avec les pages RazorUsing Layouts, partials, templates, and Tag Helpers with Razor Pages

Les pages Razor fonctionnent avec toutes les fonctionnalités du moteur de vue Razor.Pages work with all the capabilities of the Razor view engine. Les dispositions, partiels, modèles, Tag Helpers, _ViewStart.cshtml et _ViewImports.cshtml fonctionnent de la même façon que pour les vues Razor classiques.Layouts, partials, templates, Tag Helpers, _ViewStart.cshtml, _ViewImports.cshtml work in the same way they do for conventional Razor views.

Nous allons nettoyer un peu cette page en tirant parti de certaines de ces fonctionnalités.Let's declutter this page by taking advantage of some of those capabilities.

Ajoutez une page de disposition à Pages/Shared/_Layout.cshtml :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>

La disposition :The Layout:

  • Contrôle la disposition de chaque page (à moins que la page ne refuse la disposition).Controls the layout of each page (unless the page opts out of layout).
  • Importe des structures HTML telles que JavaScript et les feuilles de style.Imports HTML structures such as JavaScript and stylesheets.

Pour plus d’informations, consultez Page de disposition.See layout page for more information.

La propriété Layout est définie dans Pages/_ViewStart.cshtml :The Layout property is set in Pages/_ViewStart.cshtml:

@{
    Layout = "_Layout";
}

La disposition est dans le dossier Pages/Shared.The layout is in the Pages/Shared folder. Les pages recherchent d’autres vues (dispositions, modèles, partiels) hiérarchiquement, en commençant dans le même dossier que la page active.Pages look for other views (layouts, templates, partials) hierarchically, starting in the same folder as the current page. Une disposition dans le dossier Pages/Shared peut être utilisée à partir de n’importe quelle page Razor sous le dossier Pages.A layout in the Pages/Shared folder can be used from any Razor page under the Pages folder.

Le fichier de disposition doit être placé dans le dossier Pages/Shared.The layout file should go in the Pages/Shared folder.

Nous vous recommandons de ne pas placer le fichier de disposition dans le dossier Views/Shared.We recommend you not put the layout file in the Views/Shared folder. Views/Shared est un modèle de vues MVC.Views/Shared is an MVC views pattern. Les pages Razor sont censées s’appuyer sur la hiérarchie des dossiers, pas sur les conventions de chemins.Razor Pages are meant to rely on folder hierarchy, not path conventions.

La recherche de vue à partir d’une page Razor inclut le dossier Pages.View search from a Razor Page includes the Pages folder. Les dispositions, modèles et partiels que vous utilisez avec les contrôleurs MVC et les vues Razor conventionnelles fonctionnent simplement.The layouts, templates, and partials you're using with MVC controllers and conventional Razor views just work.

Ajoutez un fichier Pages/_ViewImports.cshtml :Add a Pages/_ViewImports.cshtml file:

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

@namespace est expliqué plus loin dans le didacticiel.@namespace is explained later in the tutorial. La directive @addTagHelper permet de bénéficier des Tag Helpers intégrés dans toutes les pages du dossier Pages.The @addTagHelper directive brings in the built-in Tag Helpers to all the pages in the Pages folder.

Quand la directive @namespace est utilisée explicitement sur une page :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>

La directive définit l’espace de noms pour la page.The directive sets the namespace for the page. La directive @model n’a pas besoin d’inclure l’espace de noms.The @model directive doesn't need to include the namespace.

Quand la directive @namespace est contenue dans _ViewImports.cshtml, l’espace de noms spécifié fournit le préfixe de l’espace de noms généré dans la Page qui importe la directive @namespace.When the @namespace directive is contained in _ViewImports.cshtml, the specified namespace supplies the prefix for the generated namespace in the Page that imports the @namespace directive. Le reste de l’espace de noms généré (la partie suffixe) est le chemin relatif séparé par un point entre le dossier contenant _ViewImports.cshtml et le dossier contenant la page.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.

Par exemple, la classe PageModel Pages/Customers/Edit.cshtml.cs définit explicitement l’espace de noms :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.

Le fichier Pages/_ViewImports.cshtml définit l’espace de noms suivant :The Pages/_ViewImports.cshtml file sets the following namespace:

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

L’espace de noms généré pour la page Razor Pages/Customers/Edit.cshtml est identique à la classe PageModel.The generated namespace for the Pages/Customers/Edit.cshtml Razor Page is the same as the PageModel class.

@namespace fonctionne également avec les vues Razor classiques.@namespace also works with conventional Razor views.

Le fichier de vue Pages/Create.cshtml d’origine :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>

Le fichier vue Pages/Create.cshtml mis à jour :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>

Le projet de démarrage de pages Razor contient Pages/_ValidationScriptsPartial.cshtml, qui connecte la validation côté client.The Razor Pages starter project contains the Pages/_ValidationScriptsPartial.cshtml, which hooks up client-side validation.

Pour plus d'informations sur les affichages partiels, consultez Vues partielles dans ASP.NET Core.For more information on partial views, see Vues partielles dans ASP.NET Core.

Génération d’URL pour les pagesURL generation for Pages

La page Create, illustrée précédemment, utilise 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");
}

L’application a la structure de fichiers/dossiers suivante :The app has the following file/folder structure:

  • /Pages/Pages

    • Index.cshtmlIndex.cshtml

    • /Customers/Customers

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

Une fois l’opération réussie, les pages Pages/Customers/Create.cshtml et Pages/Customers/Edit.cshtml redirigent vers Pages/Index.cshtml.The Pages/Customers/Create.cshtml and Pages/Customers/Edit.cshtml pages redirect to Pages/Index.cshtml after success. La chaîne /Index fait partie de l’URI pour accéder à la page précédente.The string /Index is part of the URI to access the preceding page. La chaîne /Index peut être utilisée pour générer l’URI de la page Pages/Index.cshtml.The string /Index can be used to generate URIs to the Pages/Index.cshtml page. Exemple :For example:

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

Le nom de la page est le chemin de la page à partir du dossier racine /Pages avec un / devant (par exemple, /Index).The page name is the path to the page from the root /Pages folder including a leading / (for example, /Index). Les exemples de génération d’URL précédents offrent des options améliorées et des capacités fonctionnelles sur le codage en dur d’une URL.The preceding URL generation samples offer enhanced options and functional capabilities over hardcoding a URL. La génération d’URL utilise le routage et peut générer et encoder des paramètres en fonction de la façon dont l’itinéraire est défini dans le chemin de destination.URL generation uses routing and can generate and encode parameters according to how the route is defined in the destination path.

La génération d’URL pour les pages prend en charge les noms relatifs.URL generation for pages supports relative names. Le tableau suivant montre la page Index sélectionnée avec différents paramètres RedirectToPage à partir de Pages/Customers/Create.cshtml :The following table shows which Index page is selected with different RedirectToPage parameters from Pages/Customers/Create.cshtml:

RedirectToPage(x)RedirectToPage(x) PagePage
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") et RedirectToPage("../Index") sont des noms relatifs.RedirectToPage("Index"), RedirectToPage("./Index"), and RedirectToPage("../Index") are relative names. Le paramètre RedirectToPage est combiné avec le chemin de la page active pour calculer le nom de la page de destination.The RedirectToPage parameter is combined with the path of the current page to compute the name of the destination page.

La liaison de nom relatif est utile lors de la création de sites avec une structure complexe.Relative name linking is useful when building sites with a complex structure. Si vous utilisez des noms relatifs pour établir une liaison entre les pages d’un dossier, vous pouvez renommer ce dossier.If you use relative names to link between pages in a folder, you can rename that folder. Tous les liens fonctionneront encore (car ils n’incluent pas le nom du dossier).All the links still work (because they didn't include the folder name).

Pour rediriger vers une page située dans une autre Zone, spécifiez la zone :To redirect to a page in a different Area, specify the area:

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

Pour plus d'informations, consultez Zones dans ASP.NET Core.For more information, see Zones dans ASP.NET Core.

Attribut ViewDataViewData attribute

Les données peuvent être passées à une page avec ViewDataAttribute.Data can be passed to a page with ViewDataAttribute. Les valeurs des propriétés définies sur des contrôleurs ou sur des modèles de page Razor décorés avec [ViewData] sont stockées et chargées à partir de ViewDataDictionary.Properties on controllers or Razor Page models decorated with [ViewData] have their values stored and loaded from the ViewDataDictionary.

Dans l’exemple suivant, AboutModel contient une propriété Title décorée avec [ViewData].In the following example, the AboutModel contains a Title property decorated with [ViewData]. La propriété Title a pour valeur le titre de la page À propos de :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()
    {
    }
}

Dans la page À propos de, accédez à la propriété Title en tant que propriété de modèle :In the About page, access the Title property as a model property:

<h1>@Model.Title</h1>

Dans la disposition, le titre est lu à partir du dictionnaire ViewData :In the layout, the title is read from the ViewData dictionary:

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

TempDataTempData

ASP.NET Core expose la propriété TempData sur un contrôleur.ASP.NET Core exposes the TempData property on a controller. Cette propriété stocke les données jusqu’à ce qu’elles soient lues.This property stores data until it's read. Vous pouvez utiliser les méthodes Keep et Peek pour examiner les données sans suppression.The Keep and Peek methods can be used to examine the data without deletion. TempData est utile pour la redirection, quand des données sont nécessaires pour plusieurs requêtes.TempData is useful for redirection, when data is needed for more than a single request.

Le code suivant définit la valeur de Message à l’aide de TempData :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");
    }
}

Le balisage suivant dans le fichier Pages/Customers/Index.cshtml affiche la valeur de Message à l’aide de TempData.The following markup in the Pages/Customers/Index.cshtml file displays the value of Message using TempData.

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

Le modèle de page Pages/Customers/Index.cshtml.cs applique l’attribut [TempData] à la propriété Message.The Pages/Customers/Index.cshtml.cs page model applies the [TempData] attribute to the Message property.

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

Pour plus d’informations, consultez TempData.For more information, see TempData .

Plusieurs gestionnaires par pageMultiple handlers per page

La page suivante génère un balisage pour deux gestionnaires en utilisant le Tag Helper asp-page-handler :The following page generates markup for two handlers using the asp-page-handler Tag Helper:

@page
@model CreateFATHModel

<html>
<body>
    <p>
        Enter your name.
    </p>
    <div asp-validation-summary="All"></div>
    <form method="POST">
        <div>Name: <input asp-for="Customer.Name" /></div>
        <input type="submit" asp-page-handler="JoinList" value="Join" />
        <input type="submit" asp-page-handler="JoinListUC" value="JOIN UC" />
    </form>
</body>
</html>

Le formulaire dans l’exemple précédent contient deux boutons d’envoi, chacun utilisant FormActionTagHelper pour envoyer à une URL différente.The form in the preceding example has two submit buttons, each using the FormActionTagHelper to submit to a different URL. L’attribut asp-page-handler est un complément de asp-page.The asp-page-handler attribute is a companion to asp-page. asp-page-handler génère des URL qui envoient à chacune des méthodes de gestionnaire définies par une page.asp-page-handler generates URLs that submit to each of the handler methods defined by a page. asp-page n’est pas spécifié, car l’exemple établit une liaison à la page active.asp-page isn't specified because the sample is linking to the current page.

Le modèle de page :The page model:

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

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

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

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

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

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

        public async Task<IActionResult> OnPostJoinListUCAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            Customer.Name = Customer.Name?.ToUpper();
            return await OnPostJoinListAsync();
        }
    }
}

Le code précédent utilise des méthodes de gestionnaire nommées.The preceding code uses named handler methods. Pour créer des méthodes de gestionnaire nommées, il faut prendre le texte dans le nom après On<HTTP Verb> et avant Async (le cas échéant).Named handler methods are created by taking the text in the name after On<HTTP Verb> and before Async (if present). Dans l’exemple précédent, les méthodes de page sont OnPostJoinListAsync et OnPostJoinListUCAsync.In the preceding example, the page methods are OnPostJoinListAsync and OnPostJoinListUCAsync. Avec OnPost et Async supprimés, les noms des gestionnaires sont JoinList et 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" />

Avec le code précédent, le chemin d’URL qui envoie à OnPostJoinListAsync est 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. Le chemin d’URL qui envoie à OnPostJoinListUCAsync est https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH?handler=JoinListUC.

Routes personnaliséesCustom routes

Utilisez la directive @page pour :Use the @page directive to:

  • Spécifier une route personnalisée vers une page.Specify a custom route to a page. Par exemple, la route vers la page À propos peut être définie sur /Some/Other/Path avec @page "/Some/Other/Path".For example, the route to the About page can be set to /Some/Other/Path with @page "/Some/Other/Path".
  • Ajouter des segments à la route par défaut d’une page.Append segments to a page's default route. Par exemple, un segment « item » peut être ajouté à la route par défaut d’une page avec @page "item".For example, an "item" segment can be added to a page's default route with @page "item".
  • Ajouter des paramètres à la route par défaut d’une page.Append parameters to a page's default route. Par exemple, un paramètre d’ID, id, peut être nécessaire pour une page avec @page "{id}".For example, an ID parameter, id, can be required for a page with @page "{id}".

Un chemin relatif racine désigné par un tilde (~) au début du chemin est pris en charge.A root-relative path designated by a tilde (~) at the beginning of the path is supported. Par exemple, @page "~/Some/Other/Path" est identique à @page "/Some/Other/Path".For example, @page "~/Some/Other/Path" is the same as @page "/Some/Other/Path".

Vous pouvez remplacer la chaîne de requête ?handler=JoinList dans l’URL par un segment de routage /JoinList en spécifiant le modèle de routage @page "{handler?}".You can change the query string ?handler=JoinList in the URL to a route segment /JoinList by specifying the route template @page "{handler?}".

Si vous ne voulez pas avoir la chaîne de requête ?handler=JoinList dans l’URL, vous pouvez changer l’itinéraire pour placer le nom du gestionnaire dans la partie chemin de l’URL.If you don't like the query string ?handler=JoinList in the URL, you can change the route to put the handler name in the path portion of the URL. Vous pouvez personnaliser l’itinéraire en ajoutant un modèle d’itinéraire placé entre des guillemets doubles après la directive @page.You can customize the route 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>

Avec le code précédent, le chemin d’URL qui envoie à OnPostJoinListAsync est https://localhost:5001/Customers/CreateFATH/JoinList.Using the preceding code, the URL path that submits to OnPostJoinListAsync is https://localhost:5001/Customers/CreateFATH/JoinList. Le chemin d’URL qui envoie à OnPostJoinListUCAsync est https://localhost:5001/Customers/CreateFATH/JoinListUC.The URL path that submits to OnPostJoinListUCAsync is https://localhost:5001/Customers/CreateFATH/JoinListUC.

Le ? suivant handler signifie que le paramètre d’itinéraire est facultatif.The ? following handler means the route parameter is optional.

Configuration et paramètresConfiguration and settings

Pour configurer les options avancées, utilisez la méthode d’extension AddRazorPagesOptions sur le générateur MVC :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");
        });
}

Actuellement, vous pouvez utiliser RazorPagesOptions pour définir le répertoire racine pour les pages, ou ajouter des conventions de modèle d’application pour les pages.Currently you can use the RazorPagesOptions to set the root directory for pages, or add application model conventions for pages. Nous permettrons à l’avenir une plus grande extensibilité en ce sens.We'll enable more extensibility this way in the future.

Pour précompiler des vues, consultez Compilation de vue Razor.To precompile views, see Razor view compilation .

Téléchargez ou affichez des exemples de code.Download or view sample code.

Consultez Bien démarrer avec les pages Razor qui s’appuie sur cette introduction.See Get started with Razor Pages, which builds on this introduction.

Spécifier que les pages Razor se trouvent à la racine du contenuSpecify that Razor Pages are at the content root

Par défaut, les pages Razor sont associées à la racine /Pages.By default, Razor Pages are rooted in the /Pages directory. Ajoutez WithRazorPagesAtContentRoot à AddMvc pour spécifier que vos Razor pages se trouvent à la racine du contenu (ContentRootPath) de l’application :Add WithRazorPagesAtContentRoot to AddMvc to specify that your Razor Pages are at the content root (ContentRootPath) of the app:

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

Spécifier que les pages Razor se trouvent dans un répertoire racine personnaliséSpecify that Razor Pages are at a custom root directory

Ajoutez WithRazorPagesRoot à AddMvc pour spécifier que vos pages Razor se trouvent dans le répertoire racine personnalisé de l’application (fournissez un chemin relatif) :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");

Ressources supplémentairesAdditional resources