Tag Helpers dans les formulaires dans ASP.NET Core
Par Rick Anderson, N. Taylor Mullen, Dave Paquette et Jerrie Pelser
Ce document montre comment utiliser les formulaires, ainsi que les éléments HTML couramment utilisés dans un formulaire. L’élément HTML Form fournit le principal mécanisme utilisé par les applications web pour publier des données sur le serveur. La majeure partie de ce document décrit les Tag Helpers et explique comment ils peuvent vous aider à créer des formulaires HTML robustes. Nous vous recommandons de lire Introduction aux Tag Helpers avant de lire ce document.
Dans de nombreux cas, les HTML Helpers offrent une autre approche par rapport à un Tag Helper spécifique. Toutefois, il est clair que les Tag Helpers ne remplacent pas les HTML Helpers, et qu’il n’existe pas toujours un Tag Helper pour chaque HTML Helper. Quand une alternative HTML Helper existe, elle est mentionnée.
Tag Helper Form
Génère pour la valeur d’attribut HTML <FORM>
action
d’un routage nommé ou d’une action de contrôleur MVCGénère un jeton de vérification de requête masqué pour empêcher la falsification de requête intersites (quand il est utilisé avec l’attribut
[ValidateAntiForgeryToken]
dans la méthode d’action HTTP Post)Fournit l’attribut
asp-route-<Parameter Name>
, où<Parameter Name>
est ajouté aux valeurs de routage. Les paramètresrouteValues
pourHtml.BeginForm
etHtml.BeginRouteForm
fournissent des fonctionnalités similaires.Comporte une alternative HTML Helper avec
Html.BeginForm
etHtml.BeginRouteForm
Exemple :
<form asp-controller="Demo" asp-action="Register" method="post">
<!-- Input and Submit elements -->
</form>
Le Tag Helper Form ci-dessus génère le code HTML suivant :
<form method="post" action="/Demo/Register">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Le runtime MVC génère la valeur de l’attribut action
à partir des attributs asp-controller
et asp-action
du Tag Helper Form. Le Tag Helper Form génère également un jeton de vérification de requête masqué pour empêcher la falsification de requête intersites (quand il est utilisé avec l’attribut [ValidateAntiForgeryToken]
dans la méthode d’action HTTP Post). Il est difficile de protéger un formulaire HTML contre une falsification de requête intersites. Le Tag Helper Form se charge de fournir ce service à votre place.
Utilisation d’un routage nommé
L’attribut Tag Helper asp-route
peut également générer des balises pour l’attribut HTML action
. Une application avec une route nommée register
pourrait utiliser le balisage suivant pour la page d’inscription :
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>
Un bon nombre des vues du dossier Vues/Compte (généré quand vous créez une application web avec des comptes d’utilisateurs individuels) contiennent l’attribut asp-route-returnurl :
<form asp-controller="Account" asp-action="Login"
asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">
Notes
Avec les modèles intégrés, returnUrl
est uniquement rempli automatiquement quand vous essayez d’accéder à une ressource autorisée sans l’authentification ou l’autorisation nécessaire. Quand vous tentez d’effectuer un accès non autorisé, l’intergiciel (middleware) de sécurité vous redirige vers la page de connexion avec le returnUrl
défini.
Le Tag Helper Form Action
Le Tag Helper Form Action génère l’attribut formaction
sur la balise <button ...>
ou <input type="image" ...>
générée. L’attribut formaction
détermine où un formulaire envoie ses données. Il se lie aux éléments <input> de type image
et aux éléments <button>. Le Tag Helper Form Action permet l’utilisation de plusieurs attributs AnchorTagHelper asp-
pour contrôler quel lien formaction
est généré pour l’élément correspondant.
Attributs AnchorTagHelper pris en charge pour contrôler la valeur de formaction
:
Attribut | Description |
---|---|
asp-controller | Nom du contrôleur. |
asp-action | Nom de la méthode d’action. |
asp-area | Nom de la zone. |
asp-page | Nom de la page Razor. |
asp-page-handler | Nom du gestionnaire de page Razor. |
asp-route | Nom de l'itinéraire. |
asp-route-{value} | Valeur de routage d’URL unique. Par exemple : asp-route-id="1234" . |
asp-all-route-data | Toutes les valeurs d’itinéraire. |
asp-fragment | Fragment d’URL. |
Exemple d’envoi au contrôleur
Le balisage suivant envoie le formulaire à l’action Index
de HomeController
lorsque input ou button est sélectionnée :
<form method="post">
<button asp-controller="Home" asp-action="Index">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-controller="Home"
asp-action="Index">
</form>
Le balisage précédent génère le code HTML suivant :
<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>
Exemple d’envoi à la page
Le balisage suivant envoie le formulaire à la page RazorAbout
:
<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>
Le balisage précédent génère le code HTML suivant :
<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>
Exemple d’envoi à l’itinéraire
Prenez le point de terminaison /Home/Test
:
public class HomeController : Controller
{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}
Le balisage suivant envoie le formulaire au point de terminaison /Home/Test
.
<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>
Le balisage précédent génère le code HTML suivant :
<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>
Tag Helper Input
Le Tag Helper Input lie un élément HTML <input> à une expression de modèle dans votre vue razor.
Syntaxe :
<input asp-for="<Expression Name>">
Tag Helper Input :
Génère les attributs HTML
id
etname
pour le nom d’expression spécifié dans l’attributasp-for
.asp-for="Property1.Property2"
équivaut àm => m.Property1.Property2
. Nom de l’expression utilisée pour la valeur de l’attributasp-for
. Pour plus d’informations, consultez la section Noms d’expressions.Définit la valeur de l’attribut HTML
type
en fonction du type de modèle et des attributs d’annotation de données appliqués à la propriété de modèleNe remplace pas la valeur de l’attribut HTML
type
quand une valeur est spécifiéeGénère des attributs de validation HTML5 à partir des attributs d’annotation de données appliqués aux propriétés de modèle
Chevauche des fonctionnalités HTML Helper avec
Html.TextBoxFor
etHtml.EditorFor
. Pour plus d’informations, consultez la section Alternatives HTML Helper au Tag Helper Input.Fournit un typage fort. Si le nom de la propriété change et si vous ne mettez pas à jour le Tag Helper, vous obtenez une erreur similaire à celle-ci :
An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately. Type expected 'RegisterViewModel' does not contain a definition for 'Email' and no extension method 'Email' accepting a first argument of type 'RegisterViewModel' could be found (are you missing a using directive or an assembly reference?)
Le Tag Helper Input
définit l’attribut HTML type
en fonction du type .NET. Le tableau suivant liste certains types .NET usuels et le type HTML généré (tous les types .NET ne sont pas listés).
Type .NET | Type d’entrée |
---|---|
Bool | type="checkbox" |
String | type="text" |
DateTime | type="datetime-local" |
Byte | type="number" |
Int | type="number" |
Single, Double | type="number" |
Le tableau suivant présente des attributs d’annotations de données usuels que le Tag Helper Input mappe à des types d’entrée spécifiques (tous les attributs de validation ne sont pas listés) :
Attribut | Type d’entrée |
---|---|
[EmailAddress] | type="email" |
[Url] | type="url" |
[HiddenInput] | type="hidden" |
[Phone] | type="tel" |
[DataType(DataType.Password)] | type="password" |
[DataType(DataType.Date)] | type="date" |
[DataType(DataType.Time)] | type="time" |
Exemple :
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
@model RegisterViewModel
<form asp-controller="Demo" asp-action="RegisterInput" method="post">
<label>Email: <input asp-for="Email" /></label> <br />
<label>Password: <input asp-for="Password" /></label><br />
<button type="submit">Register</button>
</form>
Le code ci-dessus génère le code HTML suivant :
<form method="post" action="/Demo/RegisterInput">
Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value=""><br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password"><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Les annotations de données appliquées aux propriétés Email
et Password
génèrent des métadonnées pour le modèle. Le Tag Helper Input consomme les métadonnées du modèle et génère les attributs HTML5 data-val-*
(consultez Validation du modèle). Ces attributs décrivent les validateurs à attacher aux champs d’entrée. Cela permet d’effectuer une validation HTML5 et jQuery discrète. Les attributs discrets ont le format data-val-rule="Error Message"
, rule étant le nom de la règle de validation (comme data-val-required
, data-val-email
, data-val-maxlength
, etc.). Si un message d’erreur est fourni dans l’attribut, il s’affiche en tant que valeur de l’attribut data-val-rule
. Il existe également des attributs ayant la forme data-val-ruleName-argumentName="argumentValue"
et qui fournissent des détails supplémentaires sur la règle, par exemple data-val-maxlength-max="1024"
.
Lorsque plusieurs contrôles input
sont liés à une même propriété, les contrôles générés partagent le même id
, ce qui rend le balisage généré non valide. Pour éviter les doublons, spécifiez explicitement l’attribut id
pour chaque contrôle.
Rendu d’entrée masquée pour les cases à cocher
Les cases à cocher en HTML5 n’envoient pas de valeur lorsqu’elles sont décochées. Pour permettre l’envoi d’une valeur par défaut pour une case à cocher non cochée, le Tag Helper Input génère une entrée masquée supplémentaire pour les cases à cocher.
Prenons l’exemple du balisage Razor suivant qui utilise le Tag Helper Input pour une propriété de modèle booléenne IsChecked
:
<form method="post">
<input asp-for="@Model.IsChecked" />
<button type="submit">Submit</button>
</form>
Le balisage Razor précédent génère un balisage HTML qui se présente comme suit :
<form method="post">
<input name="IsChecked" type="checkbox" value="true" />
<button type="submit">Submit</button>
<input name="IsChecked" type="hidden" value="false" />
</form>
Le balisage HTML précédent présente une entrée masquée supplémentaire nommée IsChecked
dont la valeur est false
. Par défaut, cette entrée masquée est affichée à la fin du formulaire. Lorsque le formulaire est envoyé :
- Si l’entrée de case à cocher
IsChecked
est cochée,true
etfalse
sont envoyés en tant que valeurs. - Si l’entrée de case à cocher
IsChecked
est décochée, seule la valeur d’entrée masquéefalse
est envoyée.
Le processus de liaison de modèle ASP.NET Core lit uniquement la première valeur lors de la liaison à une valeur bool
, ce qui donne true
pour les cases à cocher cochées et false
pour les cases à cocher non cochées.
Pour configurer le comportement du rendu d’entrée masquée, définissez la propriété CheckBoxHiddenInputRenderMode dans MvcViewOptions.HtmlHelperOptions. Par exemple :
services.Configure<MvcViewOptions>(options =>
options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode =
CheckBoxHiddenInputRenderMode.None);
Le code précédent désactive le rendu d’entrée masquée pour les cases à cocher en définissant CheckBoxHiddenInputRenderMode
sur CheckBoxHiddenInputRenderMode.None. Pour connaître tous les modes de rendu disponibles, consultez l’énumération CheckBoxHiddenInputRenderMode.
Alternatives HTML Helper au Tag Helper Input
Html.TextBox
, Html.TextBoxFor
, Html.Editor
et Html.EditorFor
ont des fonctionnalités qui chevauchent celles du Tag Helper Input. Le Tag Helper Input définit automatiquement l’attribut type
, contrairement à Html.TextBox
et Html.TextBoxFor
. Html.Editor
et Html.EditorFor
gèrent les collections, les objets complexes et les modèles, contrairement au Tag Helper Input. Le Tag Helper Input, Html.EditorFor
et Html.TextBoxFor
sont fortement typés (ils utilisent des expressions lambda), contrairement à Html.TextBox
et Html.Editor
(qui utilisent des noms d’expression).
HtmlAttributes
@Html.Editor()
et @Html.EditorFor()
utilisent une entrée ViewDataDictionary
spéciale nommée htmlAttributes
durant l’exécution de leurs modèles par défaut. Ce comportement est éventuellement amélioré à l’aide des paramètres additionalViewData
. La clé « htmlAttributes » ne respecte pas la casse. La clé « htmlAttributes » est prise en charge de manière similaire à l’objet htmlAttributes
passé aux Helpers d’entrée tels que @Html.TextBox()
.
@Html.EditorFor(model => model.YourProperty,
new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })
Noms d’expressions
La valeur de l’attribut asp-for
est un ModelExpression
et correspond au côté droit d’une expression lambda. Ainsi, asp-for="Property1"
devient m => m.Property1
dans le code généré, ce qui explique pourquoi vous n’avez pas besoin de le faire commencer par Model
. Vous pouvez utiliser le caractère « @ » pour débuter une expression inline avant m.
:
@{
var joe = "Joe";
}
<input asp-for="@joe">
Génère ce qui suit :
<input type="text" id="joe" name="joe" value="Joe">
Avec les propriétés de collection, asp-for="CollectionProperty[23].Member"
génère le même nom que asp-for="CollectionProperty[i].Member"
quand i
a la valeur 23
.
Quand ASP.NET Core MVC calcule la valeur de ModelExpression
, plusieurs sources sont inspectées, notamment ModelState
. Prenez le cas de <input type="text" asp-for="Name">
. L’attribut value
calculé est la première valeur non-null des éléments suivants :
- Entrée
ModelState
avec la clé « Name ». - Résultat de l’expression
Model.Name
.
Navigation dans les propriétés enfants
Vous pouvez également accéder aux propriétés enfants à l’aide du chemin de propriété du modèle de vue. Prenons le cas d’une classe de modèle plus complexe qui contient une propriété enfant Address
.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}
public class RegisterAddressViewModel
{
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public AddressViewModel Address { get; set; }
}
Dans la vue, nous effectuons une liaison à Address.AddressLine1
:
@model RegisterAddressViewModel
<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
<label>Email: <input asp-for="Email" /></label> <br />
<label>Password: <input asp-for="Password" /></label><br />
<label>Address: <input asp-for="Address.AddressLine1" /></label><br />
<button type="submit">Register</button>
</form>
Le code HTML suivant est généré pour Address.AddressLine1
:
<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">
Noms d’expressions et collections
Dans cet exemple, un modèle contient un tableau de Colors
:
public class Person
{
public List<string> Colors { get; set; }
public int Age { get; set; }
}
Méthode d’action :
public IActionResult Edit(int id, int colorIndex)
{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}
Le code Razor suivant montre comment accéder à un élément Color
spécifique :
@model Person
@{
var index = (int)ViewData["index"];
}
<form asp-controller="ToDo" asp-action="Edit" method="post">
@Html.EditorFor(m => m.Colors[index])
<label asp-for="Age"></label>
<input asp-for="Age" /><br />
<button type="submit">Post</button>
</form>
Le modèle Views/Shared/EditorTemplates/String.cshtml
:
@model string
<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />
Exemple utilisant List<T>
:
public class ToDoItem
{
public string Name { get; set; }
public bool IsDone { get; set; }
}
Le code Razor suivant montre comment itérer sur une collection :
@model List<ToDoItem>
<form asp-controller="ToDo" asp-action="Edit" method="post">
<table>
<tr> <th>Name</th> <th>Is Done</th> </tr>
@for (int i = 0; i < Model.Count; i++)
{
<tr>
@Html.EditorFor(model => model[i])
</tr>
}
</table>
<button type="submit">Save</button>
</form>
Le modèle Views/Shared/EditorTemplates/ToDoItem.cshtml
:
@model ToDoItem
<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>
@*
This template replaces the following Razor which evaluates the indexer three times.
<td>
<label asp-for="@Model[i].Name"></label>
@Html.DisplayFor(model => model[i].Name)
</td>
<td>
<input asp-for="@Model[i].IsDone" />
</td>
*@
Utilisez si possible foreach
quand la valeur doit être employée dans un contexte équivalent à asp-for
ou Html.DisplayFor
. En règle générale, préférez for
à foreach
(si le scénario le permet), car il n’a pas besoin d’allouer un énumérateur. Toutefois, l’évaluation d’un indexeur dans une expression LINQ peut s’avérer coûteuse et doit être réduite.
Notes
L’exemple de code commenté ci-dessus montre comment remplacer l’expression lambda par l’opérateur @
pour accéder à chaque ToDoItem
dans la liste.
Tag Helper Textarea
Le Tag Helper Textarea Tag Helper
est similaire au Tag Helper Input.
Génère les attributs
id
etname
, ainsi que les attributs de validation des données du modèle pour un élément <textarea>>.Fournit un typage fort.
Alternative HTML Helper :
Html.TextAreaFor
Exemple :
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}
@model DescriptionViewModel
<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">
<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>
Le code HTML suivant est généré :
<form method="post" action="/Demo/RegisterTextArea">
<textarea data-val="true"
data-val-maxlength="The field Description must be a string or array type with a maximum length of '1024'."
data-val-maxlength-max="1024"
data-val-minlength="The field Description must be a string or array type with a minimum length of '5'."
data-val-minlength-min="5"
id="Description" name="Description">
</textarea>
<button type="submit">Test</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Tag Helper Label
Génère la légende d’étiquette et l’attribut
for
d’un élément <label>> pour un nom d’expressionAlternative HTML Helper :
Html.LabelFor
.
Le Label Tag Helper
offre les avantages suivants par rapport à un élément d’étiquette HTML pur :
Vous obtenez automatiquement la valeur d’étiquette descriptive à partir de l’attribut
Display
. Le nom d’affichage prévu peut changer plus tard. La combinaison de l’attributDisplay
et du Tag Helper Label appliqueDisplay
partout où il est utilisé.Moins de balises dans le code source
Typage fort avec la propriété de modèle.
Exemple :
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}
@model SimpleViewModel
<form asp-controller="Demo" asp-action="RegisterLabel" method="post">
<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>
Le code HTML suivant est généré pour l’élément <label>
:
<label for="Email">Email Address</label>
Le Tag Helper Label a généré la valeur « Email » pour l’attribut for
, qui représente l’ID associé à l’élément <input>
. Les Tag Helpers génèrent des éléments id
et for
cohérents pour qu’ils puissent être correctement associés. La légende de cet exemple provient de l’attribut Display
. Si le modèle ne contient pas d’attribut Display
, la légende correspond au nom de propriété de l’expression. Pour remplacer la légende par défaut, ajoutez une légende à l’intérieur de la balise label (étiquette).
Tag Helpers Validation
Il existe deux Tag Helpers Validation. Le Validation Message Tag Helper
(qui affiche un message de validation pour une seule propriété de votre modèle) et le Validation Summary Tag Helper
(qui affiche un récapitulatif des erreurs de validation). Le Input Tag Helper
ajoute des attributs de validation HTML5 côté client aux éléments d’entrée en fonction des attributs d’annotation de données pour vos classes de modèle. La validation est également effectuée sur le serveur. Le Tag Helper Validation affiche ces messages d’erreur quand une erreur de validation se produit.
Le Tag Helper Validation Message
Ajoute l’attribut HTML5
data-valmsg-for="property"
à l’élément span qui attache les messages d’erreur de validation du champ d’entrée de la propriété spécifiée du modèle. Quand une erreur de validation côté client se produit, jQuery affiche le message d’erreur dans l’élément<span>
.La validation a également lieu sur le serveur. Il arrive que JavaScript soit désactivé sur les clients et qu’une partie de la validation puisse être effectuée uniquement côté serveur.
Alternative HTML Helper :
Html.ValidationMessageFor
Le Validation Message Tag Helper
est utilisé avec l’attribut asp-validation-for
sur un élément HTML span.
<span asp-validation-for="Email"></span>
Le Tag Helper Validation Message génère le code HTML suivant :
<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>
En règle générale, vous utilisez le Validation Message Tag Helper
après un Tag Helper Input
pour la même propriété. Dans ce cas, les messages d’erreur de validation s’affichent près de l’entrée qui a provoqué l’erreur.
Notes
Vous devez avoir une vue avec les références de script JavaScript et jQuery appropriées pour la validation côté client. Pour plus d’informations, consultez Validation de modèle.
Quand une erreur de validation côté serveur se produit (par exemple, quand vous disposez d’une validation personnalisée côté serveur ou quand la validation côté client est désactivée), MVC place ce message d’erreur dans le corps de l’élément <span>
.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>
Le Tag Helper Validation Summary
Cible les éléments
<div>
avec les attributsasp-validation-summary
Alternative HTML Helper :
@Html.ValidationSummary
Le Validation Summary Tag Helper
est utilisé pour afficher un récapitulatif des messages de validation. La valeur de l’attribut asp-validation-summary
peut correspondre à l’une des valeurs suivantes :
asp-validation-summary | Messages de validation affichés |
---|---|
All |
Niveau de la propriété et du modèle |
ModelOnly |
Modèle |
None |
None |
Exemple
Dans l’exemple suivant, le modèle de données possède des attributs DataAnnotation
, ce qui génère des messages d’erreur de validation pour l’élément <input>
. Quand une erreur de validation se produit, le Tag Helper Validation affiche le message d’erreur :
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
@model RegisterViewModel
<form asp-controller="Demo" asp-action="RegisterValidation" method="post">
<div asp-validation-summary="ModelOnly"></div>
<label>Email: <input asp-for="Email" /></label> <br />
<span asp-validation-for="Email"></span><br />
<label>Password: <input asp-for="Password" /></label><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>
Code HTML généré (quand le modèle est valide) :
<form action="/DemoReg/Register" method="post">
<label>Email: <input name="Email" id="Email" type="email" value=""
data-val-required="The Email field is required."
data-val-email="The Email field is not a valid email address."
data-val="true"></label><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Email"></span><br>
<label>Password: <input name="Password" id="Password" type="password"
data-val-required="The Password field is required." data-val="true"></label><br>
<span class="field-validation-valid" data-valmsg-replace="true"
data-valmsg-for="Password"></span><br>
<button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Tag Helper Select
Génère l’élément select et les éléments option associés pour les propriétés de votre modèle.
Comporte une alternative HTML Helper avec
Html.DropDownListFor
etHtml.ListBoxFor
Le Select Tag Helper
asp-for
spécifie le nom de propriété du modèle de l’élément sélectionner, tandis que asp-items
spécifie les éléments option. Par exemple :
<select asp-for="Country" asp-items="Model.Countries"></select>
Exemple :
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace FormsTagHelper.ViewModels
{
public class CountryViewModel
{
public string Country { get; set; }
public List<SelectListItem> Countries { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
}
}
La méthode Index
initialise CountryViewModel
, définit le pays sélectionné et le passe à la vue Index
.
public IActionResult Index()
{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}
La méthode HTTP POST Index
affiche la sélection :
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}
// If we got this far, something failed; redisplay form.
return View(model);
}
Vue Index
:
@model CountryViewModel
<form asp-controller="Home" asp-action="Index" method="post">
<select asp-for="Country" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>
Qui génère le code HTML suivant (avec « CA » sélectionné) :
<form method="post" action="/">
<select id="Country" name="Country">
<option value="MX">Mexico</option>
<option selected="selected" value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Notes
Nous déconseillons d’utiliser ViewBag
ou ViewData
avec le Tag Helper Select. Un modèle de vue est plus robuste et, en général, moins problématique pour fournir des métadonnées MVC.
La valeur de l’attribut asp-for
est un cas particulier et ne nécessite pas de préfixe Model
, contrairement aux autres attributs du Tag Helper (par exemple asp-items
)
<select asp-for="Country" asp-items="Model.Countries"></select>
Liaison d’enum
Il est souvent pratique d’utiliser <select>
avec une propriété enum
et de générer les éléments SelectListItem
à partir des valeurs de enum
.
Exemple :
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}
La méthode GetEnumSelectList
génère un objet SelectList
pour un enum.
@model CountryEnumViewModel
<form asp-controller="Home" asp-action="IndexEnum" method="post">
<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList<CountryEnum>()">
</select>
<br /><button type="submit">Register</button>
</form>
Vous pouvez marquer votre liste d’énumérateurs avec l’attribut Display
pour obtenir une IU plus riche :
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}
Le code HTML suivant est généré :
<form method="post" action="/Home/IndexEnum">
<select data-val="true" data-val-required="The EnumCountry field is required."
id="EnumCountry" name="EnumCountry">
<option value="0">United Mexican States</option>
<option value="1">United States of America</option>
<option value="2">Canada</option>
<option value="3">France</option>
<option value="4">Germany</option>
<option selected="selected" value="5">Spain</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Groupe d’options
L’élément HTML <optgroup>> est généré quand le modèle de vue contient un ou plusieurs objets SelectListGroup
.
CountryViewModelGroup
regroupe les éléments SelectListItem
dans les groupes « North America » et « Europe » :
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };
Countries = new List<SelectListItem>
{
new SelectListItem
{
Value = "MEX",
Text = "Mexico",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = NorthAmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
new SelectListItem
{
Value = "DE",
Text = "Germany",
Group = EuropeGroup
}
};
}
public string Country { get; set; }
public List<SelectListItem> Countries { get; }
Les deux groupes sont affichés ci-dessous :
Code HTML généré :
<form method="post" action="/Home/IndexGroup">
<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Sélection multiple
Le Tag Helper Select génère automatiquement l’attribut multiple = "multiple" si la propriété spécifiée dans l’attribut asp-for
est IEnumerable
. Par exemple, le modèle suivant :
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace FormsTagHelper.ViewModels
{
public class CountryViewModelIEnumerable
{
public IEnumerable<string> CountryCodes { get; set; }
public List<SelectListItem> Countries { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "ES", Text = "Spain" },
new SelectListItem { Value = "DE", Text = "Germany"}
};
}
}
Avec la vue suivante :
@model CountryViewModelIEnumerable
<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">
<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>
Génère le code HTML suivant :
<form method="post" action="/Home/IndexMultiSelect">
<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
Aucune sélection
Si vous constatez que l’option « not specified » est utilisée dans plusieurs pages, vous pouvez créer un modèle pour éviter de répéter le code HTML :
@model CountryViewModel
<form asp-controller="Home" asp-action="IndexEmpty" method="post">
@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>
Le modèle Views/Shared/EditorTemplates/CountryViewModel.cshtml
:
@model CountryViewModel
<select asp-for="Country" asp-items="Model.Countries">
<option value="">--none--</option>
</select>
L’ajout d’éléments HTML <option>> ne se limite pas au cas Pas de sélection. Par exemple, la vue et la méthode d’action suivante génèrent du code HTML similaire au code ci-dessus :
public IActionResult IndexNone()
{
var model = new CountryViewModel();
model.Countries.Insert(0, new SelectListItem("<none>", ""));
return View(model);
}
@model CountryViewModel
<form asp-controller="Home" asp-action="IndexEmpty" method="post">
<select asp-for="Country">
<option value=""><none></option>
<option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
</form>
L’élément <option>
approprié est sélectionné (il contient l’attribut selected="selected"
) en fonction de la valeur actuelle de Country
.
public IActionResult IndexOption(int id)
{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}
<form method="post" action="/Home/IndexEmpty">
<select id="Country" name="Country">
<option value=""><none></option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>