Partie 6, Méthodes et vues de contrôleur dans ASP.NET Core
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Par Rick Anderson
Nous avons une bonne ébauche de l’application de films, mais sa présentation n’est pas idéale, par exemple, ReleaseDate devrait être écrit en deux mots.
Ouvrez le fichier Models/Movie.cs
et ajoutez les lignes en surbrillance ci-dessous :
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
Les DataAnnotations
sont expliquées dans le tutoriel suivant. L’attribut Display spécifie les éléments à afficher pour le nom d’un champ (dans le cas présent, « Release Date » au lieu de « ReleaseDate »). L’attribut DataType spécifie le type des données (Date). Les informations d’heures stockées dans le champ ne s’affichent donc pas.
L’annotation de données [Column(TypeName = "decimal(18, 2)")]
est nécessaire pour qu’Entity Framework Core puisse correctement mapper Price
en devise dans la base de données. Pour plus d’informations, consultez Types de données.
Accédez au contrôleur Movies
et maintenez le pointeur de la souris sur un lien Edit pour afficher l’URL cible.
Les liens Edit, Details et Delete sont générés par le Tag Helper d’ancre Core MVC dans le fichier Views/Movies/Index.cshtml
.
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
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. Dans le code ci-dessus, AnchorTagHelper
génère dynamiquement la valeur de l’attribut HTML href
à partir de la méthode d’action du contrôleur et de l’ID de route. Vous utilisez Afficher la source à partir de votre navigateur favori ou utilisez les outils de développement pour examiner le balisage généré. Une partie du code HTML généré est affichée ci-dessous :
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rappelez-vous le format du routage défini dans le fichier Program.cs
:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core traduit https://localhost:5001/Movies/Edit/4
en une requête à la méthode d’action Edit
du contrôleur Movies
avec un paramètre Id
de 4. (Les méthodes de contrôleur sont également appelées méthodes d’action.)
Les Tag Helpers sont l’une des nouvelles fonctionnalités les plus populaires dans ASP.NET Core. Pour plus d'informations, consultez Ressources supplémentaires.
Ouvrez le contrôleur Movies
et examinez les deux méthodes d’action Edit
. Le code suivant montre la méthode HTTP GET Edit
, qui extrait le film et renseigne le formulaire de modification généré par le fichier RazorEdit.cshtml
.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le code suivant montre la méthode HTTP POST Edit
, qui traite les valeurs de film publiées :
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [Bind]
est l’un des moyens qui permettent d’assurer une protection contre la sur-publication. Vous devez inclure dans l’attribut [Bind]
uniquement les propriétés que vous souhaitez modifier. Pour plus d’informations, consultez Protéger votre contrôleur contre la sur-publication. Les ViewModels fournissent une alternative pour empêcher la sur-publication.
Notez que la deuxième méthode d’action Edit
est précédée de l’attribut [HttpPost]
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut HttpPost
indique que cette méthode Edit
peut être appelée uniquement pour les requêtes POST
. Vous pouvez appliquer l’attribut [HttpGet]
à la première méthode Edit, mais cela n’est pas nécessaire car [HttpGet]
est la valeur par défaut.
L’attribut ValidateAntiForgeryToken
est utilisé pour lutter contre la falsification d’une requête. Il est associé à un jeton anti-falsification généré dans le fichier de la vue de modification (Views/Movies/Edit.cshtml
). Le fichier de la vue de modification génère le jeton anti-falsification avec le Form Tag Helper.
<form asp-action="Edit">
Le Form Tag Helper génère un jeton anti-falsification masqué qui doit correspondre au jeton anti-falsification généré [ValidateAntiForgeryToken]
dans la méthode Edit
du contrôleur Movies. Pour plus d’informations, consultez Prévenir les attaques par falsification de requête intersites (XSRF/CSRF) dans ASP.NET Core.
La méthode HttpGet Edit
prend le paramètre ID
du film, recherche le film à l’aide de la méthode Entity Framework FindAsync
, et retourne le film sélectionné à la vue Edit. Si un film est introuvable, l’erreur NotFound
(HTTP 404) est retournée.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quand le système de génération de modèles automatique a créé la vue Edit, il a examiné la classe Movie
et a créé le code pour restituer les éléments <label>
et <input>
de chaque propriété de la classe. L’exemple suivant montre la vue Edit qui a été générée par le système de génération de modèles automatique de Visual Studio :
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Notez que le modèle de vue comporte une instruction @model MvcMovie.Models.Movie
en haut du fichier. @model MvcMovie.Models.Movie
indique que la vue s’attend à ce que le modèle pour le modèle de vue soit de type Movie
.
Le code de génération de modèles automatique utilise plusieurs méthodes Tag Helper afin de rationaliser le balisage HTML. Le Tag Helper Label affiche le nom du champ (« Title », « ReleaseDate », « Genre » ou « Price »). Le Tag Helper Input affiche l’élément <input>
HTML. Le Tag Helper Validation affiche les messages de validation associés à cette propriété.
Exécutez l’application et accédez à l’URL /Movies
. Cliquez sur un lien Edit. Dans le navigateur, affichez la source de la page. Le code HTML généré pour l’élément <form>
est indiqué ci-dessous.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Les éléments <input>
sont dans un élément HTML <form>
dont l’attribut action
est défini de façon à publier à l’URL /Movies/Edit/id
. Les données du formulaire sont publiées au serveur en cas de clic sur le bouton Save
. La dernière ligne avant l’élément </form>
de fermeture montre le jeton XSRF masqué généré par le Tag Helper Form.
Traitement de la requête POST
Le code suivant montre la version [HttpPost]
de la méthode d’action Edit
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [ValidateAntiForgeryToken]
valide le jeton XSRF masqué généré par le générateur de jetons anti-falsification dans le Form Tag Helper
Le système de liaison de modèle prend les valeurs de formulaire publiées et crée un objet Movie
qui est passé en tant que paramètre movie
. La propriété ModelState.IsValid
vérifie que les données envoyées dans le formulaire peuvent être utilisées pour changer (modifier ou mettre à jour) un objet Movie
. Si les données sont valides, elles sont enregistrées. Les données de film mises à jour (modifiées) sont enregistrées dans la base de données en appelant la méthode SaveChangesAsync
du contexte de base de données. Après avoir enregistré les données, le code redirige l’utilisateur vers la méthode d’action Index
de la classe MoviesController
, qui affiche la collection de films, avec notamment les modifications qui viennent d’être apportées.
Avant que le formulaire soit publié sur le serveur, la validation côté client vérifie les règles de validation sur les champs. En cas d’erreur de validation, un message d’erreur s’affiche et le formulaire n’est pas publié. Si JavaScript est désactivé, aucune validation côté client n’est effectuée, mais le serveur détecte les valeurs publiées qui ne sont pas valides, et les valeurs de formulaire sont réaffichées avec des messages d’erreur. Plus loin dans ce didacticiel, nous examinerons la Validation du modèle plus en détail. Le Tag Helper Validation dans le modèle de vue Views/Movies/Edit.cshtml
se charge de l’affichage des messages d’erreur appropriés.
Toutes les méthodes HttpGet
du contrôleur Movies suivent un modèle similaire. Elles reçoivent un objet de film (ou une liste d’objets, dans le cas de Index
) et passent l’objet (modèle) à la vue. La méthode Create
passe un objet de film vide à la vue Create
. Toutes les méthodes qui créent, modifient, suppriment ou changent d’une quelconque manière des données le font dans la surcharge [HttpPost]
de la méthode. Modifier des données dans une méthode HTTP GET
présente un risque pour la sécurité. La modification des données dans une méthode HTTP GET
enfreint également les bonnes pratiques HTTP et le modèle architectural REST, qui spécifie que les demandes GET ne doivent pas changer l’état de votre application. En d’autres termes, une opération GET doit être sûre, ne doit avoir aucun effet secondaire et ne doit pas modifier vos données persistantes.
Ressources supplémentaires
- Globalisation et localisation
- Introduction aux Tag Helpers
- Créer des Tag Helpers
- Éviter les attaques de falsification de demande intersites (XSRF/CSRF) dans ASP.NET Core
- Protéger votre contrôleur contre la sur-publication
- ViewModels
- Tag Helper de formulaire
- Tag Helper Input
- Tag Helper Label
- Tag Helper de sélection
- Tag Helper Validation
Nous avons une bonne ébauche de l’application de films, mais sa présentation n’est pas idéale, par exemple, ReleaseDate devrait être écrit en deux mots.
Ouvrez le fichier Models/Movie.cs
et ajoutez les lignes en surbrillance ci-dessous :
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
Les DataAnnotations
sont expliquées dans le tutoriel suivant. L’attribut Display spécifie les éléments à afficher pour le nom d’un champ (dans le cas présent, « Release Date » au lieu de « ReleaseDate »). L’attribut DataType spécifie le type des données (Date). Les informations d’heures stockées dans le champ ne s’affichent donc pas.
L’annotation de données [Column(TypeName = "decimal(18, 2)")]
est nécessaire pour qu’Entity Framework Core puisse correctement mapper Price
en devise dans la base de données. Pour plus d’informations, consultez Types de données.
Accédez au contrôleur Movies
et maintenez le pointeur de la souris sur un lien Edit pour afficher l’URL cible.
Les liens Edit, Details et Delete sont générés par le Tag Helper d’ancre Core MVC dans le fichier Views/Movies/Index.cshtml
.
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
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. Dans le code ci-dessus, AnchorTagHelper
génère dynamiquement la valeur de l’attribut HTML href
à partir de la méthode d’action du contrôleur et de l’ID de route. Vous utilisez Afficher la source à partir de votre navigateur favori ou utilisez les outils de développement pour examiner le balisage généré. Une partie du code HTML généré est affichée ci-dessous :
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rappelez-vous le format du routage défini dans le fichier Program.cs
:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core traduit https://localhost:5001/Movies/Edit/4
en une requête à la méthode d’action Edit
du contrôleur Movies
avec un paramètre Id
de 4. (Les méthodes de contrôleur sont également appelées méthodes d’action.)
Les Tag Helpers sont l’une des nouvelles fonctionnalités les plus populaires dans ASP.NET Core. Pour plus d'informations, consultez Ressources supplémentaires.
Ouvrez le contrôleur Movies
et examinez les deux méthodes d’action Edit
. Le code suivant montre la méthode HTTP GET Edit
, qui extrait le film et renseigne le formulaire de modification généré par le fichier RazorEdit.cshtml
.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le code suivant montre la méthode HTTP POST Edit
, qui traite les valeurs de film publiées :
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [Bind]
est l’un des moyens qui permettent d’assurer une protection contre la sur-publication. Vous devez inclure dans l’attribut [Bind]
uniquement les propriétés que vous souhaitez modifier. Pour plus d’informations, consultez Protéger votre contrôleur contre la sur-publication. Les ViewModels fournissent une alternative pour empêcher la sur-publication.
Notez que la deuxième méthode d’action Edit
est précédée de l’attribut [HttpPost]
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut HttpPost
indique que cette méthode Edit
peut être appelée uniquement pour les requêtes POST
. Vous pouvez appliquer l’attribut [HttpGet]
à la première méthode Edit, mais cela n’est pas nécessaire car [HttpGet]
est la valeur par défaut.
L’attribut ValidateAntiForgeryToken
est utilisé pour lutter contre la falsification d’une requête. Il est associé à un jeton anti-falsification généré dans le fichier de la vue de modification (Views/Movies/Edit.cshtml
). Le fichier de la vue de modification génère le jeton anti-falsification avec le Form Tag Helper.
<form asp-action="Edit">
Le Form Tag Helper génère un jeton anti-falsification masqué qui doit correspondre au jeton anti-falsification généré [ValidateAntiForgeryToken]
dans la méthode Edit
du contrôleur Movies. Pour plus d’informations, consultez Prévenir les attaques par falsification de requête intersites (XSRF/CSRF) dans ASP.NET Core.
La méthode HttpGet Edit
prend le paramètre ID
du film, recherche le film à l’aide de la méthode Entity Framework FindAsync
, et retourne le film sélectionné à la vue Edit. Si un film est introuvable, l’erreur NotFound
(HTTP 404) est retournée.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quand le système de génération de modèles automatique a créé la vue Edit, il a examiné la classe Movie
et a créé le code pour restituer les éléments <label>
et <input>
de chaque propriété de la classe. L’exemple suivant montre la vue Edit qui a été générée par le système de génération de modèles automatique de Visual Studio :
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Notez que le modèle de vue comporte une instruction @model MvcMovie.Models.Movie
en haut du fichier. @model MvcMovie.Models.Movie
indique que la vue s’attend à ce que le modèle pour le modèle de vue soit de type Movie
.
Le code de génération de modèles automatique utilise plusieurs méthodes Tag Helper afin de rationaliser le balisage HTML. Le Tag Helper Label affiche le nom du champ (« Title », « ReleaseDate », « Genre » ou « Price »). Le Tag Helper Input affiche l’élément <input>
HTML. Le Tag Helper Validation affiche les messages de validation associés à cette propriété.
Exécutez l’application et accédez à l’URL /Movies
. Cliquez sur un lien Edit. Dans le navigateur, affichez la source de la page. Le code HTML généré pour l’élément <form>
est indiqué ci-dessous.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Les éléments <input>
sont dans un élément HTML <form>
dont l’attribut action
est défini de façon à publier à l’URL /Movies/Edit/id
. Les données du formulaire sont publiées au serveur en cas de clic sur le bouton Save
. La dernière ligne avant l’élément </form>
de fermeture montre le jeton XSRF masqué généré par le Tag Helper Form.
Traitement de la requête POST
Le code suivant montre la version [HttpPost]
de la méthode d’action Edit
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [ValidateAntiForgeryToken]
valide le jeton XSRF masqué généré par le générateur de jetons anti-falsification dans le Form Tag Helper
Le système de liaison de modèle prend les valeurs de formulaire publiées et crée un objet Movie
qui est passé en tant que paramètre movie
. La propriété ModelState.IsValid
vérifie que les données envoyées dans le formulaire peuvent être utilisées pour changer (modifier ou mettre à jour) un objet Movie
. Si les données sont valides, elles sont enregistrées. Les données de film mises à jour (modifiées) sont enregistrées dans la base de données en appelant la méthode SaveChangesAsync
du contexte de base de données. Après avoir enregistré les données, le code redirige l’utilisateur vers la méthode d’action Index
de la classe MoviesController
, qui affiche la collection de films, avec notamment les modifications qui viennent d’être apportées.
Avant que le formulaire soit publié sur le serveur, la validation côté client vérifie les règles de validation sur les champs. En cas d’erreur de validation, un message d’erreur s’affiche et le formulaire n’est pas publié. Si JavaScript est désactivé, aucune validation côté client n’est effectuée, mais le serveur détecte les valeurs publiées qui ne sont pas valides, et les valeurs de formulaire sont réaffichées avec des messages d’erreur. Plus loin dans ce didacticiel, nous examinerons la Validation du modèle plus en détail. Le Tag Helper Validation dans le modèle de vue Views/Movies/Edit.cshtml
se charge de l’affichage des messages d’erreur appropriés.
Toutes les méthodes HttpGet
du contrôleur Movies suivent un modèle similaire. Elles reçoivent un objet de film (ou une liste d’objets, dans le cas de Index
) et passent l’objet (modèle) à la vue. La méthode Create
passe un objet de film vide à la vue Create
. Toutes les méthodes qui créent, modifient, suppriment ou changent d’une quelconque manière des données le font dans la surcharge [HttpPost]
de la méthode. Modifier des données dans une méthode HTTP GET
présente un risque pour la sécurité. La modification des données dans une méthode HTTP GET
enfreint également les bonnes pratiques HTTP et le modèle architectural REST, qui spécifie que les demandes GET ne doivent pas changer l’état de votre application. En d’autres termes, une opération GET doit être sûre, ne doit avoir aucun effet secondaire et ne doit pas modifier vos données persistantes.
Ressources supplémentaires
- Globalisation et localisation
- Introduction aux Tag Helpers
- Créer des Tag Helpers
- Éviter les attaques de falsification de demande intersites (XSRF/CSRF) dans ASP.NET Core
- Protéger votre contrôleur contre la sur-publication
- ViewModels
- Tag Helper de formulaire
- Tag Helper Input
- Tag Helper Label
- Tag Helper de sélection
- Tag Helper Validation
Nous avons une bonne ébauche de l’application de films, mais sa présentation n’est pas idéale, par exemple, ReleaseDate devrait être écrit en deux mots.
Ouvrez le fichier Models/Movie.cs
et ajoutez les lignes en surbrillance ci-dessous :
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models;
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
Les DataAnnotations
sont expliquées dans le tutoriel suivant. L’attribut Display spécifie les éléments à afficher pour le nom d’un champ (dans le cas présent, « Release Date » au lieu de « ReleaseDate »). L’attribut DataType spécifie le type des données (Date). Les informations d’heures stockées dans le champ ne s’affichent donc pas.
L’annotation de données [Column(TypeName = "decimal(18, 2)")]
est nécessaire pour qu’Entity Framework Core puisse correctement mapper Price
en devise dans la base de données. Pour plus d’informations, consultez Types de données.
Accédez au contrôleur Movies
et maintenez le pointeur de la souris sur un lien Edit pour afficher l’URL cible.
Les liens Edit, Details et Delete sont générés par le Tag Helper d’ancre Core MVC dans le fichier Views/Movies/Index.cshtml
.
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
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. Dans le code ci-dessus, AnchorTagHelper
génère dynamiquement la valeur de l’attribut HTML href
à partir de la méthode d’action du contrôleur et de l’ID de route. Vous utilisez Afficher la source à partir de votre navigateur favori ou utilisez les outils de développement pour examiner le balisage généré. Une partie du code HTML généré est affichée ci-dessous :
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rappelez-vous le format du routage défini dans le fichier Program.cs
:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core traduit https://localhost:5001/Movies/Edit/4
en une requête à la méthode d’action Edit
du contrôleur Movies
avec un paramètre Id
de 4. (Les méthodes de contrôleur sont également appelées méthodes d’action.)
Les Tag Helpers sont l’une des nouvelles fonctionnalités les plus populaires dans ASP.NET Core. Pour plus d'informations, consultez Ressources supplémentaires.
Ouvrez le contrôleur Movies
et examinez les deux méthodes d’action Edit
. Le code suivant montre la méthode HTTP GET Edit
, qui extrait le film et renseigne le formulaire de modification généré par le fichier RazorEdit.cshtml
.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le code suivant montre la méthode HTTP POST Edit
, qui traite les valeurs de film publiées :
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [Bind]
est l’un des moyens qui permettent d’assurer une protection contre la sur-publication. Vous devez inclure dans l’attribut [Bind]
uniquement les propriétés que vous souhaitez modifier. Pour plus d’informations, consultez Protéger votre contrôleur contre la sur-publication. Les ViewModels fournissent une alternative pour empêcher la sur-publication.
Notez que la deuxième méthode d’action Edit
est précédée de l’attribut [HttpPost]
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut HttpPost
indique que cette méthode Edit
peut être appelée uniquement pour les requêtes POST
. Vous pouvez appliquer l’attribut [HttpGet]
à la première méthode Edit, mais cela n’est pas nécessaire car [HttpGet]
est la valeur par défaut.
L’attribut ValidateAntiForgeryToken
est utilisé pour lutter contre la falsification d’une requête. Il est associé à un jeton anti-falsification généré dans le fichier de la vue de modification (Views/Movies/Edit.cshtml
). Le fichier de la vue de modification génère le jeton anti-falsification avec le Form Tag Helper.
<form asp-action="Edit">
Le Form Tag Helper génère un jeton anti-falsification masqué qui doit correspondre au jeton anti-falsification généré [ValidateAntiForgeryToken]
dans la méthode Edit
du contrôleur Movies. Pour plus d’informations, consultez Prévenir les attaques par falsification de requête intersites (XSRF/CSRF) dans ASP.NET Core.
La méthode HttpGet Edit
prend le paramètre ID
du film, recherche le film à l’aide de la méthode Entity Framework FindAsync
, et retourne le film sélectionné à la vue Edit. Si un film est introuvable, l’erreur NotFound
(HTTP 404) est retournée.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quand le système de génération de modèles automatique a créé la vue Edit, il a examiné la classe Movie
et a créé le code pour restituer les éléments <label>
et <input>
de chaque propriété de la classe. L’exemple suivant montre la vue Edit qui a été générée par le système de génération de modèles automatique de Visual Studio :
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Notez que le modèle de vue comporte une instruction @model MvcMovie.Models.Movie
en haut du fichier. @model MvcMovie.Models.Movie
indique que la vue s’attend à ce que le modèle pour le modèle de vue soit de type Movie
.
Le code de génération de modèles automatique utilise plusieurs méthodes Tag Helper afin de rationaliser le balisage HTML. Le Tag Helper Label affiche le nom du champ (« Title », « ReleaseDate », « Genre » ou « Price »). Le Tag Helper Input affiche l’élément <input>
HTML. Le Tag Helper Validation affiche les messages de validation associés à cette propriété.
Exécutez l’application et accédez à l’URL /Movies
. Cliquez sur un lien Edit. Dans le navigateur, affichez la source de la page. Le code HTML généré pour l’élément <form>
est indiqué ci-dessous.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Les éléments <input>
sont dans un élément HTML <form>
dont l’attribut action
est défini de façon à publier à l’URL /Movies/Edit/id
. Les données du formulaire sont publiées au serveur en cas de clic sur le bouton Save
. La dernière ligne avant l’élément </form>
de fermeture montre le jeton XSRF masqué généré par le Tag Helper Form.
Traitement de la requête POST
Le code suivant montre la version [HttpPost]
de la méthode d’action Edit
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [ValidateAntiForgeryToken]
valide le jeton XSRF masqué généré par le générateur de jetons anti-falsification dans le Form Tag Helper
Le système de liaison de modèle prend les valeurs de formulaire publiées et crée un objet Movie
qui est passé en tant que paramètre movie
. La propriété ModelState.IsValid
vérifie que les données envoyées dans le formulaire peuvent être utilisées pour changer (modifier ou mettre à jour) un objet Movie
. Si les données sont valides, elles sont enregistrées. Les données de film mises à jour (modifiées) sont enregistrées dans la base de données en appelant la méthode SaveChangesAsync
du contexte de base de données. Après avoir enregistré les données, le code redirige l’utilisateur vers la méthode d’action Index
de la classe MoviesController
, qui affiche la collection de films, avec notamment les modifications qui viennent d’être apportées.
Avant que le formulaire soit publié sur le serveur, la validation côté client vérifie les règles de validation sur les champs. En cas d’erreur de validation, un message d’erreur s’affiche et le formulaire n’est pas publié. Si JavaScript est désactivé, aucune validation côté client n’est effectuée, mais le serveur détecte les valeurs publiées qui ne sont pas valides, et les valeurs de formulaire sont réaffichées avec des messages d’erreur. Plus loin dans ce didacticiel, nous examinerons la Validation du modèle plus en détail. Le Tag Helper Validation dans le modèle de vue Views/Movies/Edit.cshtml
se charge de l’affichage des messages d’erreur appropriés.
Toutes les méthodes HttpGet
du contrôleur Movies suivent un modèle similaire. Elles reçoivent un objet de film (ou une liste d’objets, dans le cas de Index
) et passent l’objet (modèle) à la vue. La méthode Create
passe un objet de film vide à la vue Create
. Toutes les méthodes qui créent, modifient, suppriment ou changent d’une quelconque manière des données le font dans la surcharge [HttpPost]
de la méthode. Modifier des données dans une méthode HTTP GET
présente un risque pour la sécurité. La modification des données dans une méthode HTTP GET
enfreint également les bonnes pratiques HTTP et le modèle architectural REST, qui spécifie que les demandes GET ne doivent pas changer l’état de votre application. En d’autres termes, une opération GET doit être sûre, ne doit avoir aucun effet secondaire et ne doit pas modifier vos données persistantes.
Ressources supplémentaires
- Globalisation et localisation
- Introduction aux Tag Helpers
- Créer des Tag Helpers
- Éviter les attaques de falsification de demande intersites (XSRF/CSRF) dans ASP.NET Core
- Protéger votre contrôleur contre la sur-publication
- ViewModels
- Tag Helper de formulaire
- Tag Helper Input
- Tag Helper Label
- Tag Helper de sélection
- Tag Helper Validation
Nous avons une bonne ébauche de l’application de films, mais sa présentation n’est pas idéale, par exemple, ReleaseDate devrait être écrit en deux mots.
Ouvrez le fichier Models/Movie.cs
et ajoutez les lignes en surbrillance ci-dessous :
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string? Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string? Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
}
Les DataAnnotations
sont expliquées dans le tutoriel suivant. L’attribut Display spécifie les éléments à afficher pour le nom d’un champ (dans le cas présent, « Release Date » au lieu de « ReleaseDate »). L’attribut DataType spécifie le type des données (Date). Les informations d’heures stockées dans le champ ne s’affichent donc pas.
L’annotation de données [Column(TypeName = "decimal(18, 2)")]
est nécessaire pour qu’Entity Framework Core puisse correctement mapper Price
en devise dans la base de données. Pour plus d’informations, consultez Types de données.
Accédez au contrôleur Movies
et maintenez le pointeur de la souris sur un lien Edit pour afficher l’URL cible.
Les liens Edit, Details et Delete sont générés par le Tag Helper d’ancre Core MVC dans le fichier Views/Movies/Index.cshtml
.
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
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. Dans le code ci-dessus, AnchorTagHelper
génère dynamiquement la valeur de l’attribut HTML href
à partir de la méthode d’action du contrôleur et de l’ID de route. Vous utilisez Afficher la source à partir de votre navigateur favori ou utilisez les outils de développement pour examiner le balisage généré. Une partie du code HTML généré est affichée ci-dessous :
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rappelez-vous le format du routage défini dans le fichier Program.cs
:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
ASP.NET Core traduit https://localhost:5001/Movies/Edit/4
en une requête à la méthode d’action Edit
du contrôleur Movies
avec un paramètre Id
de 4. (Les méthodes de contrôleur sont également appelées méthodes d’action.)
Les Tag Helpers sont une fonctionnalité populaire dans ASP.NET Core. Pour plus d’informations sur ces éléments, consultez Ressources supplémentaires.
Ouvrez le contrôleur Movies
et examinez les deux méthodes d’action Edit
. Le code suivant montre la méthode HTTP GET Edit
, qui extrait le film et renseigne le formulaire de modification généré par le fichier RazorEdit.cshtml
.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le code suivant montre la méthode HTTP POST Edit
, qui traite les valeurs de film publiées :
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [Bind]
est l’un des moyens qui permettent d’assurer une protection contre la sur-publication. Vous devez inclure dans l’attribut [Bind]
uniquement les propriétés que vous souhaitez modifier. Pour plus d’informations, consultez Protéger votre contrôleur contre la sur-publication. Les ViewModels fournissent une alternative pour empêcher la sur-publication.
Notez que la deuxième méthode d’action Edit
est précédée de l’attribut [HttpPost]
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut HttpPost
indique que cette méthode Edit
peut être appelée uniquement pour les requêtes POST
. Vous pouvez appliquer l’attribut [HttpGet]
à la première méthode Edit, mais cela n’est pas nécessaire car [HttpGet]
est la valeur par défaut.
L’attribut ValidateAntiForgeryToken
est utilisé pour lutter contre la falsification d’une requête. Il est associé à un jeton anti-falsification généré dans le fichier de la vue de modification (Views/Movies/Edit.cshtml
). Le fichier de la vue de modification génère le jeton anti-falsification avec le Form Tag Helper.
<form asp-action="Edit">
Le Form Tag Helper génère un jeton anti-falsification masqué qui doit correspondre au jeton anti-falsification généré [ValidateAntiForgeryToken]
dans la méthode Edit
du contrôleur Movies. Pour plus d’informations, consultez Prévenir les attaques par falsification de requête intersites (XSRF/CSRF) dans ASP.NET Core.
La méthode HttpGet Edit
prend le paramètre ID
du film, recherche le film à l’aide de la méthode Entity Framework FindAsync
, et retourne le film sélectionné à la vue Edit. Si un film est introuvable, l’erreur NotFound
(HTTP 404) est retournée.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quand le système de génération de modèles automatique a créé la vue Edit, il a examiné la classe Movie
et a créé le code pour restituer les éléments <label>
et <input>
de chaque propriété de la classe. L’exemple suivant montre la vue Edit qui a été générée par le système de génération de modèles automatique de Visual Studio :
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Notez que le modèle de vue comporte une instruction @model MvcMovie.Models.Movie
en haut du fichier. @model MvcMovie.Models.Movie
indique que la vue s’attend à ce que le modèle pour le modèle de vue soit de type Movie
.
Le code de génération de modèles automatique utilise plusieurs méthodes Tag Helper afin de rationaliser le balisage HTML. Le Tag Helper Label affiche le nom du champ (« Title », « ReleaseDate », « Genre » ou « Price »). Le Tag Helper Input affiche l’élément <input>
HTML. Le Tag Helper Validation affiche les messages de validation associés à cette propriété.
Exécutez l’application et accédez à l’URL /Movies
. Cliquez sur un lien Edit. Dans le navigateur, affichez la source de la page. Le code HTML généré pour l’élément <form>
est indiqué ci-dessous.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Les éléments <input>
sont dans un élément HTML <form>
dont l’attribut action
est défini de façon à publier à l’URL /Movies/Edit/id
. Les données du formulaire sont publiées au serveur en cas de clic sur le bouton Save
. La dernière ligne avant l’élément </form>
de fermeture montre le jeton XSRF masqué généré par le Tag Helper Form.
Traitement de la requête POST
Le code suivant montre la version [HttpPost]
de la méthode d’action Edit
.
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
if (id != movie.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [ValidateAntiForgeryToken]
valide le jeton XSRF masqué généré par le générateur de jetons anti-falsification dans le Form Tag Helper
Le système de liaison de modèle prend les valeurs de formulaire publiées et crée un objet Movie
qui est passé en tant que paramètre movie
. La propriété ModelState.IsValid
vérifie que les données envoyées dans le formulaire peuvent être utilisées pour changer (modifier ou mettre à jour) un objet Movie
. Si les données sont valides, elles sont enregistrées. Les données de film mises à jour (modifiées) sont enregistrées dans la base de données en appelant la méthode SaveChangesAsync
du contexte de base de données. Après avoir enregistré les données, le code redirige l’utilisateur vers la méthode d’action Index
de la classe MoviesController
, qui affiche la collection de films, avec notamment les modifications qui viennent d’être apportées.
Avant que le formulaire soit publié sur le serveur, la validation côté client vérifie les règles de validation sur les champs. En cas d’erreur de validation, un message d’erreur s’affiche et le formulaire n’est pas publié. Si JavaScript est désactivé, aucune validation côté client n’est effectuée, mais le serveur détecte les valeurs publiées qui ne sont pas valides, et les valeurs de formulaire sont réaffichées avec des messages d’erreur. Plus loin dans ce didacticiel, nous examinerons la Validation du modèle plus en détail. Le Tag Helper Validation dans le modèle de vue Views/Movies/Edit.cshtml
se charge de l’affichage des messages d’erreur appropriés.
Toutes les méthodes HttpGet
du contrôleur Movies suivent un modèle similaire. Elles reçoivent un objet de film (ou une liste d’objets, dans le cas de Index
) et passent l’objet (modèle) à la vue. La méthode Create
passe un objet de film vide à la vue Create
. Toutes les méthodes qui créent, modifient, suppriment ou changent d’une quelconque manière des données le font dans la surcharge [HttpPost]
de la méthode. Modifier des données dans une méthode HTTP GET
présente un risque pour la sécurité. La modification des données dans une méthode HTTP GET
enfreint également les bonnes pratiques HTTP et le modèle architectural REST, qui spécifie que les demandes GET ne doivent pas changer l’état de votre application. En d’autres termes, une opération GET doit être sûre, ne doit avoir aucun effet secondaire et ne doit pas modifier vos données persistantes.
Ressources supplémentaires
- Globalisation et localisation
- Introduction aux Tag Helpers
- Créer des Tag Helpers
- Éviter les attaques de falsification de demande intersites (XSRF/CSRF) dans ASP.NET Core
- Protéger votre contrôleur contre la sur-publication
- ViewModels
- Tag Helper de formulaire
- Tag Helper Input
- Tag Helper Label
- Tag Helper de sélection
- Tag Helper Validation
Nous avons une bonne ébauche de l’application de films, mais sa présentation n’est pas idéale, par exemple, ReleaseDate devrait être écrit en deux mots.
Ouvrez le fichier Models/Movie.cs
et ajoutez les lignes en surbrillance ci-dessous :
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MvcMovie.Models
{
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }
}
}
Nous abordons DataAnnotations dans le prochain tutoriel. L’attribut Display spécifie les éléments à afficher pour le nom d’un champ (dans le cas présent, « Release Date » au lieu de « ReleaseDate »). L’attribut DataType spécifie le type des données (Date). Les informations d’heures stockées dans le champ ne s’affichent donc pas.
L’annotation de données [Column(TypeName = "decimal(18, 2)")]
est nécessaire pour qu’Entity Framework Core puisse correctement mapper Price
en devise dans la base de données. Pour plus d’informations, consultez Types de données.
Accédez au contrôleur Movies
et maintenez le pointeur de la souris sur un lien Edit pour afficher l’URL cible.
Les liens Edit, Details et Delete sont générés par le Tag Helper d’ancre Core MVC dans le fichier Views/Movies/Index.cshtml
.
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
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. Dans le code ci-dessus, AnchorTagHelper
génère dynamiquement la valeur de l’attribut HTML href
à partir de la méthode d’action du contrôleur et de l’ID de route. Vous utilisez Afficher la source à partir de votre navigateur favori ou utilisez les outils de développement pour examiner le balisage généré. Une partie du code HTML généré est affichée ci-dessous :
<td>
<a href="/Movies/Edit/4"> Edit </a> |
<a href="/Movies/Details/4"> Details </a> |
<a href="/Movies/Delete/4"> Delete </a>
</td>
Rappelez-vous le format du routage défini dans le fichier Startup.cs
:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
ASP.NET Core traduit https://localhost:5001/Movies/Edit/4
en une requête à la méthode d’action Edit
du contrôleur Movies
avec un paramètre Id
de 4. (Les méthodes de contrôleur sont également appelées méthodes d’action.)
Pour plus d’informations sur les Tag Helpers, consultez Ressources supplémentaires.
Ouvrez le contrôleur Movies
et examinez les deux méthodes d’action Edit
. Le code suivant montre la méthode HTTP GET Edit
, qui extrait le film et renseigne le formulaire de modification généré par le fichier RazorEdit.cshtml
.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le code suivant montre la méthode HTTP POST Edit
, qui traite les valeurs de film publiées :
// POST: Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(movie);
}
L’attribut [Bind]
est l’un des moyens qui permettent d’assurer une protection contre la sur-publication. Vous devez inclure dans l’attribut [Bind]
uniquement les propriétés que vous souhaitez modifier. Pour plus d’informations, consultez Protéger votre contrôleur contre la sur-publication. Les ViewModels fournissent une alternative pour empêcher la sur-publication.
Notez que la deuxième méthode d’action Edit
est précédée de l’attribut [HttpPost]
.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut HttpPost
indique que cette méthode Edit
peut être appelée uniquement pour les requêtes POST
. Vous pouvez appliquer l’attribut [HttpGet]
à la première méthode Edit, mais cela n’est pas nécessaire car [HttpGet]
est la valeur par défaut.
L’attribut ValidateAntiForgeryToken
est utilisé pour lutter contre la falsification d’une requête. Il est associé à un jeton anti-falsification généré dans le fichier de la vue de modification (Views/Movies/Edit.cshtml
). Le fichier de la vue de modification génère le jeton anti-falsification avec le Form Tag Helper.
<form asp-action="Edit">
Le Form Tag Helper génère un jeton anti-falsification masqué qui doit correspondre au jeton anti-falsification généré [ValidateAntiForgeryToken]
dans la méthode Edit
du contrôleur Movies. Pour plus d’informations, consultez Prévenir les attaques par falsification de requête intersites (XSRF/CSRF) dans ASP.NET Core.
La méthode HttpGet Edit
prend le paramètre ID
du film, recherche le film à l’aide de la méthode Entity Framework FindAsync
, et retourne le film sélectionné à la vue Edit. Si un film est introuvable, l’erreur NotFound
(HTTP 404) est retournée.
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Quand le système de génération de modèles automatique a créé la vue Edit, il a examiné la classe Movie
et a créé le code pour restituer les éléments <label>
et <input>
de chaque propriété de la classe. L’exemple suivant montre la vue Edit qui a été générée par le système de génération de modèles automatique de Visual Studio :
@model MvcMovie.Models.Movie
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Notez que le modèle de vue comporte une instruction @model MvcMovie.Models.Movie
en haut du fichier. @model MvcMovie.Models.Movie
indique que la vue s’attend à ce que le modèle pour le modèle de vue soit de type Movie
.
Le code de génération de modèles automatique utilise plusieurs méthodes Tag Helper afin de rationaliser le balisage HTML. Le Tag Helper Label affiche le nom du champ (« Title », « ReleaseDate », « Genre » ou « Price »). Le Tag Helper Input affiche l’élément <input>
HTML. Le Tag Helper Validation affiche les messages de validation associés à cette propriété.
Exécutez l’application et accédez à l’URL /Movies
. Cliquez sur un lien Edit. Dans le navigateur, affichez la source de la page. Le code HTML généré pour l’élément <form>
est indiqué ci-dessous.
<form action="/Movies/Edit/7" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
<div class="text-danger" />
<input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" />
<div class="form-group">
<label class="control-label col-md-2" for="Genre" />
<div class="col-md-10">
<input class="form-control" type="text" id="Genre" name="Genre" value="Western" />
<span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Price" />
<div class="col-md-10">
<input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" />
<span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
</div>
<!-- Markup removed for brevity -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" />
</form>
Les éléments <input>
sont dans un élément HTML <form>
dont l’attribut action
est défini de façon à publier à l’URL /Movies/Edit/id
. Les données du formulaire sont publiées au serveur en cas de clic sur le bouton Save
. La dernière ligne avant l’élément </form>
de fermeture montre le jeton XSRF masqué généré par le Tag Helper Form.
Traitement de la requête POST
Le code suivant montre la version [HttpPost]
de la méthode d’action Edit
.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
L’attribut [ValidateAntiForgeryToken]
valide le jeton XSRF masqué généré par le générateur de jetons anti-falsification dans le Form Tag Helper
Le système de liaison de modèle prend les valeurs de formulaire publiées et crée un objet Movie
qui est passé en tant que paramètre movie
. La propriété ModelState.IsValid
vérifie que les données envoyées dans le formulaire peuvent être utilisées pour changer (modifier ou mettre à jour) un objet Movie
. Si les données sont valides, elles sont enregistrées. Les données de film mises à jour (modifiées) sont enregistrées dans la base de données en appelant la méthode SaveChangesAsync
du contexte de base de données. Après avoir enregistré les données, le code redirige l’utilisateur vers la méthode d’action Index
de la classe MoviesController
, qui affiche la collection de films, avec notamment les modifications qui viennent d’être apportées.
Avant que le formulaire soit publié sur le serveur, la validation côté client vérifie les règles de validation sur les champs. En cas d’erreur de validation, un message d’erreur s’affiche et le formulaire n’est pas publié. Si JavaScript est désactivé, aucune validation côté client n’est effectuée, mais le serveur détecte les valeurs publiées qui ne sont pas valides, et les valeurs de formulaire sont réaffichées avec des messages d’erreur. Plus loin dans ce didacticiel, nous examinerons la Validation du modèle plus en détail. Le Tag Helper Validation dans le modèle de vue Views/Movies/Edit.cshtml
se charge de l’affichage des messages d’erreur appropriés.
Toutes les méthodes HttpGet
du contrôleur Movies suivent un modèle similaire. Elles reçoivent un objet de film (ou une liste d’objets, dans le cas de Index
) et passent l’objet (modèle) à la vue. La méthode Create
passe un objet de film vide à la vue Create
. Toutes les méthodes qui créent, modifient, suppriment ou changent d’une quelconque manière des données le font dans la surcharge [HttpPost]
de la méthode. Modifier des données dans une méthode HTTP GET
présente un risque pour la sécurité. La modification des données dans une méthode HTTP GET
enfreint également les bonnes pratiques HTTP et le modèle architectural REST, qui spécifie que les demandes GET ne doivent pas changer l’état de votre application. En d’autres termes, une opération GET doit être sûre, ne doit avoir aucun effet secondaire et ne doit pas modifier vos données persistantes.
Ressources supplémentaires
- Globalisation et localisation
- Introduction aux Tag Helpers
- Créer des Tag Helpers
- Éviter les attaques de falsification de demande intersites (XSRF/CSRF) dans ASP.NET Core
- Protéger votre contrôleur contre la sur-publication
- ViewModels
- Tag Helper de formulaire
- Tag Helper Input
- Tag Helper Label
- Tag Helper de sélection
- Tag Helper Validation