Helper tag nei moduli in ASP.NET Core

Di Rick Anderson, N. Taylor Mullen, Dave Paquette e Jerrie Pelser

Questo documento illustra l'uso di helper tag Form e gli elementi HTML comunemente usati all'interno di questi. L'elemento Form del linguaggio HTML rappresenta il meccanismo principale usato dalle app Web per eseguire il postback di dati nel server. La maggior parte di questo documento descrive gli helper tag e spiega come questi consentono di creare moduli HTML solidi in modo produttivo. Prima di leggere questo documento, è consigliabile leggere Introduzione agli helper tag.

In molti casi, gli helper HTML offrono un approccio alternativo a un helper tag specifico, ma è importante tenere presente che gli helper tag non sostituiscono gli helper HTML e che non esiste un helper tag per ogni helper HTML. Se un'alternativa sotto forma di helper HTML esiste, viene citata.

Helper tag Form

L'helper tag Form:

  • Genera il valore dell'attributo HTML <FORM>action per un'azione del controller MVC o una route denominata

  • Genera un token di verifica della richiesta nascosto per impedire richieste intersito false, in caso di uso con l'attributo [ValidateAntiForgeryToken] nel metodo azione HTTP Post

  • Fornisce l'attributo asp-route-<Parameter Name>, dove <Parameter Name> viene aggiunto ai valori della route. I routeValues parametri per Html.BeginForm e Html.BeginRouteForm forniscono funzionalità simili.

  • Ha come helper HTML alternativi Html.BeginForm e Html.BeginRouteForm

Esempio:

<form asp-controller="Demo" asp-action="Register" method="post">
    <!-- Input and Submit elements -->
</form>

L'helper tag Form precedente genera il codice HTML seguente:

<form method="post" action="/Demo/Register">
    <!-- Input and Submit elements -->
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Il runtime MVC genera il valore dell'attributo action dagli attributi asp-controller e asp-action dell'helper tag Form. L'helper tag Form genera anche un token di verifica della richiesta nascosto per impedire richieste intersito false, in caso di uso con l'attributo [ValidateAntiForgeryToken] nel metodo azione HTTP Post. La protezione di un Form HTML puro da richieste intersito false è difficile, e l'helper tag Form offre questo servizio.

Uso di una route denominata

L'attributo asp-route degli helper tag può anche generare un markup per l'attributo action HTML. Un'app con una route denominata register può usare il markup seguente per la pagina di registrazione:

<form asp-route="register" method="post">
    <!-- Input and Submit elements -->
</form>

Molte delle visualizzazioni nella cartella Views/Account (generata quando si crea una nuova app Web con account utente singoli) contengono l'attributo asp-route-returnurl:

<form asp-controller="Account" asp-action="Login"
     asp-route-returnurl="@ViewData["ReturnUrl"]"
     method="post" class="form-horizontal" role="form">

Nota

Con i modelli predefiniti, returnUrl viene popolato automaticamente solo quando si tenta di accedere a una risorsa autorizzata senza aver effettuato l'autenticazione o l'autorizzazione. Se l'utente tenta un accesso non autorizzato, il middleware di sicurezza lo reindirizza alla pagina di accesso con returnUrl impostato.

Helper tag per l'azione modulo

L'helper tag per l'azione modulo genera l'attributo formaction per l'elemento <button ...> o il tag <input type="image" ...> generato. L'attributo formaction controlla se un modulo invia i dati. Viene associato agli elementi di input> di tipo image e< pulsante>.< L'helper tag per l'azione modulo consente l'utilizzo di vari attributi asp- di AnchorTagHelper per controllare quale collegamento formaction viene generato per l'elemento corrispondente.

Attributi di AnchorTagHelper supportati per controllare il valore di formaction:

Attributo Descrizione
asp-controller Nome del controller.
asp-action Nome del metodo di azione.
asp-area Nome dell'area.
asp-page Nome della Razor pagina.
asp-page-handler Nome del Razor gestore della pagina.
asp-route Nome della route.
asp-route-{value} Singolo valore di route URL. Ad esempio, asp-route-id="1234".
asp-all-route-data Tutti i valori di route.
asp-fragment Frammento di URL.

Esempio di invio al controller

Il markup seguente invia il modulo all'azione Index di HomeController quando viene selezionato l'input o un pulsante:

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

Il markup precedente genera il codice HTML seguente:

<form method="post">
    <button formaction="/Home">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Esempio di invio a una pagina

Il markup seguente invia il modulo alla AboutRazor pagina:

<form method="post">
    <button asp-page="About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Il markup precedente genera il codice HTML seguente:

<form method="post">
    <button formaction="/About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Esempio di invio a una route

Prendere in considerazione l'endpoint /Home/Test:

public class HomeController : Controller
{
    [Route("/Home/Test", Name = "Custom")]
    public string Test()
    {
        return "This is the test page";
    }
}

Il markup seguente invia il modulo all'endpoint /Home/Test.

<form method="post">
    <button asp-route="Custom">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Il markup precedente genera il codice HTML seguente:

<form method="post">
    <button formaction="/Home/Test">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>

Helper tag Input

L'helper tag di input associa un elemento di input> HTML <a un'espressione del modello nella visualizzazione razor.

Sintassi:

<input asp-for="<Expression Name>">

L'helper tag Input:

  • Genera gli attributi HTML id e name per il nome dell'espressione specificata nell'attributo asp-for. asp-for="Property1.Property2" è pari a m => m.Property1.Property2. Il nome dell'espressione viene usato come valore dell'attributo asp-for. Per altre informazioni, vedere la sezione Nomi delle espressioni.

  • Imposta il valore dell'attributo HTML type in base agli attributi relativi al tipo di modello e all'annotazione dei dati applicati alla proprietà del modello

  • Non sovrascrive il valore dell'attributo HTML type se è già stato specificato

  • Genera attributi di convalida HTML5 da attributi di annotazione dei dati applicati alla proprietà del modello

  • Sovrappone una funzionalità di helper HTML con Html.TextBoxFor e Html.EditorFor. Per i dettagli, vedere la sezione Alternative helper HTML per l'helper tag Input.

  • Consente una tipizzazione forte. Se il nome di proprietà viene modificato e non si aggiorna l'helper tag, si ottiene un errore simile al seguente:

    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?)
    

L'helper tag Input imposta l'attributo HTML type in base al tipo .NET. La tabella seguente elenca alcuni tipi .NET comuni e il tipo HTML generato. Non sono elencati tutti i tipi .NET.

Tipo .NET Tipo di input
Bool type="checkbox"
Stringa type="text"
Data/Ora type="datetime-local"
Byte type="number"
Int type="number"
Single, Double type="number"

La tabella seguente illustra alcuni attributi di annotazioni dei dati comuni di cui l'helper tag Input esegue il mapping a tipi di input specifici (non tutti gli attributi di convalida sono elencati):

Attributo Tipo di input
[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"

Esempio:

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">
    Email:  <input asp-for="Email" /> <br />
    Password: <input asp-for="Password" /><br />
    <button type="submit">Register</button>
</form>

Il codice precedente genera il codice HTML seguente:

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

Le annotazioni dei dati applicate alle proprietà Email e Password generano metadati per il modello. L'helper tag Input usa i metadati del modello e genere attributi HTML5data-val-* (vedere Convalida del modello). Questi attributi descrivono i validator da collegare ai campi di input. Ciò consente una convalida HTML5 e jQuery discreta. Gli attributi non invasivi hanno il formato data-val-rule="Error Message", dove regola è il nome della regola di convalida (ad esempio data-val-required, data-val-email, data-val-maxlengthe così via) Se viene specificato un messaggio di errore nell'attributo , viene visualizzato come valore per l'attributo data-val-rule . Esistono anche attributi di data-val-ruleName-argumentName="argumentValue" di Form che offrono dettagli aggiuntivi sulla regola, ad esempio, data-val-maxlength-max="1024" .

Quando si associano più input controlli alla stessa proprietà, i controlli generati condividono lo stesso idoggetto , che rende il mark-up generato non valido. Per evitare duplicati, specificare l'attributo id per ogni controllo in modo esplicito.

Rendering dell'input nascosto casella di controllo

Le caselle di controllo in HTML5 non inviano un valore quando sono deselezionate. Per abilitare l'invio di un valore predefinito per una casella di controllo deselezionata, l'helper tag di input genera un input nascosto aggiuntivo per le caselle di controllo.

Si consideri ad esempio il markup seguente Razor che usa l'helper tag di input per una proprietà IsCheckeddel modello booleana :

<form method="post">
    <input asp-for="@Model.IsChecked" />
    <button type="submit">Submit</button>
</form>

Il markup precedente Razor genera markup HTML simile al seguente:

<form method="post">
    <input name="IsChecked" type="checkbox" value="true" />
    <button type="submit">Submit</button>

    <input name="IsChecked" type="hidden" value="false" /> 
</form>

Il markup HTML precedente mostra un input nascosto aggiuntivo con un nome e IsChecked un valore di false. Per impostazione predefinita, il rendering dell'input nascosto viene eseguito alla fine del modulo. Quando viene inviato il modulo:

  • Se l'input della IsChecked casella di controllo è selezionato, entrambi true e false vengono inviati come valori.
  • Se l'input della IsChecked casella di controllo è deselezionato, viene inviato solo il valore false di input nascosto.

Il processo di associazione di modelli core ASP.NET legge solo il primo valore quando si esegue l'associazione a un bool valore, che restituisce true le caselle false di controllo e per le caselle di controllo deselezionate.

Per configurare il comportamento del rendering dell'input nascosto, impostare la CheckBoxHiddenInputRenderMode proprietà su MvcViewOptions.HtmlHelperOptions. Ad esempio:

services.Configure<MvcViewOptions>(options =>
    options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode =
        CheckBoxHiddenInputRenderMode.None);

Il codice precedente disabilita il rendering dell'input nascosto per le caselle di controllo impostando CheckBoxHiddenInputRenderMode su CheckBoxHiddenInputRenderMode.None. Per tutte le modalità di rendering disponibili, vedere l'enumerazione CheckBoxHiddenInputRenderMode .

Alternative helper HTML per l'helper tag Input

Html.TextBox, Html.TextBoxFor, Html.Editor e Html.EditorFor hanno funzionalità che si sovrappongono a quelle dell'helper tag Input. L'helper tag Input imposta automaticamente l'attributo type, mentre Html.TextBox e Html.TextBoxFor non lo fanno. Html.Editor e Html.EditorFor gestiscono raccolte, oggetti complessi e modelli, mentre l'helper tag Input non lo fa. L'helper Html.EditorFor tag di input e Html.TextBoxFor sono fortemente tipizzato (usano espressioni lambda) Html.TextBox e Html.Editor non sono (usano nomi di espressione).

HtmlAttributes

Quando eseguono i modelli predefiniti, @Html.Editor() e @Html.EditorFor() usano una voce ViewDataDictionary speciale denominata htmlAttributes. È possibile aumentare questo comportamento usando i parametri additionalViewData. La chiave "htmlAttributes" non fa distinzione tra maiuscole e minuscole. La chiave "htmlAttributes" viene gestita in modo analogo all'oggetto htmlAttributes passato agli helper di input come @Html.TextBox().

@Html.EditorFor(model => model.YourProperty, 
  new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

Nomi delle espressioni

Il valore dell'attributo asp-for è un ModelExpression e il lato destro di un'espressione lambda. Pertanto, asp-for="Property1" diventa m => m.Property1 nel codice generato. Per questo motivo il prefisso Model non è necessario. È possibile usare il carattere "@" per iniziare un'espressione inline, spostandolo prima di m.:

@{
  var joe = "Joe";
}

<input asp-for="@joe">

Genera quanto segue:

<input type="text" id="joe" name="joe" value="Joe">

Con le proprietà delle raccolte, asp-for="CollectionProperty[23].Member" genera lo stesso nome di asp-for="CollectionProperty[i].Member" se il valore di i è 23.

Quando ASP.NET Core MVC calcola il valore di ModelExpression, analizza diverse origini, tra cui ModelState. Considerare <input type="text" asp-for="Name">. L'attributo value calcolato è il primo valore non Null da:

  • Voce ModelState con chiave "Name".
  • Risultato dell'espressione Model.Name.

È anche possibile passare alle proprietà figlio tramite il percorso delle proprietà del modello di visualizzazione. Si consideri una classe modello più complessa contenente una proprietà Address figlio.

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

Nella visualizzazione, viene eseguita l'associazione a Address.AddressLine1:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
    Email:  <input asp-for="Email" /> <br />
    Password: <input asp-for="Password" /><br />
    Address: <input asp-for="Address.AddressLine1" /><br />
    <button type="submit">Register</button>
</form>

Per Address.AddressLine1 viene generato il codice HTML seguente:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

Nomi delle espressioni e raccolte

Esempio di modello contenente una matrice di Colors:

public class Person
{
    public List<string> Colors { get; set; }

    public int Age { get; set; }
}

Metodo di azione:

public IActionResult Edit(int id, int colorIndex)
{
    ViewData["Index"] = colorIndex;
    return View(GetPerson(id));
}

Di seguito Razor viene illustrato come accedere a un elemento specifico Color :

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

Il Views/Shared/EditorTemplates/String.cshtml modello:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

Esempio di uso di List<T>:

public class ToDoItem
{
    public string Name { get; set; }

    public bool IsDone { get; set; }
}

Di seguito Razor viene illustrato come eseguire l'iterazione su una raccolta:

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

Il Views/Shared/EditorTemplates/ToDoItem.cshtml modello:

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

foreach deve essere usato se possibile, quando il valore verrà usato in un contesto asp-for o in un contesto equivalente Html.DisplayFor. In genere for è preferibile a foreach (se lo scenario lo consente) perché non è necessario allocare un enumeratore. Tuttavia, la valutazione di un indicizzatore in un'espressione LINQ può essere dispendiosa e deve essere ridotta al minimo.

 

Nota

Il codice di esempio commentato precedente illustra come sostituire l'espressione lambda con l'operatore @ per accedere a ogni ToDoItem nell'elenco.

Helper tag Textarea

Textarea Tag Helper è simile all'helper Tag Input.

  • Genera gli attributi e name e gli attributi di convalida dei dati dal modello per un <elemento textarea>.id

  • Consente una tipizzazione forte.

  • Helper HTML alternativo: Html.TextAreaFor

Esempio:

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>

Viene generato il codice HTML seguente:

<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 &#x27;1024&#x27;."
   data-val-maxlength-max="1024"
   data-val-minlength="The field Description must be a string or array type with a minimum length of &#x27;5&#x27;."
   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>

Helper tag Label

  • Genera l'etichetta didascalia e for l'attributo in un elemento etichetta> per un <nome di espressione

  • Helper HTML alternativo: Html.LabelFor.

Offre Label Tag Helper i vantaggi seguenti rispetto a un elemento etichetta HTML puro:

  • Si ottiene automaticamente il valore descrittivo dell'etichetta dall'attributo Display. Il nome visualizzato desiderato può cambiare nel tempo e la combinazione dell'attributo Display e dell'helper tag Label applica l'attributo Display ovunque venga usato.

  • Meno markup nel codice sorgente

  • Tipizzazione forte con la proprietà del modello.

Esempio:

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>

Per l'elemento <label> viene generato il codice HTML seguente:

<label for="Email">Email Address</label>

L'helper tag Label genera il valore dell'attributo for di "Email", che è l'ID associato all'elemento <input>. Gli helper tag generano elementi id e for coerenti. In questo modo possono essere associati correttamente. La didascalia di questo esempio deriva dall'attributo Display. Se il modello non contiene un attributo Display, la didascalia corrisponde al nome della proprietà dell'espressione. Per eseguire l'override del didascalia predefinito, aggiungere un didascalia all'interno del tag di etichetta.

Helper tag di convalida

Ci sono due helper tag di convalida. Validation Message Tag Helper, che visualizza un messaggio di convalida per una singola proprietà del modello, e Validation Summary Tag Helper, che visualizza un riepilogo degli errori di convalida. Input Tag Helper aggiunge attributi di convalida sul lato client HTML5 agli elementi di input in base agli attributi di annotazione dei dati per le classi del modello. La convalida viene eseguita anche per il server. Quando si verifica un errore di convalida, l'helper tag di convalida visualizza questi messaggi di errore.

Helper tag Validation Message

  • Aggiunge l'attributo HTML5data-valmsg-for="property" all'elemento span, che collega i messaggi di errore di convalida nel campo di input della proprietà del modello specificato. Quando si verifica un errore di convalida sul lato client, jQuery visualizza il messaggio di errore nell'elemento <span>.

  • La convalida viene eseguita anche nel server. Nei client JavaScript può essere disabilitato e una parte della convalida può essere eseguita solo sul lato server.

  • Helper HTML alternativo: Html.ValidationMessageFor

Viene Validation Message Tag Helper utilizzato con l'attributo asp-validation-for su un elemento span HTML.

<span asp-validation-for="Email"></span>

L'helper tag Validation Message genera il codice HTML seguente:

<span class="field-validation-valid"
  data-valmsg-for="Email"
  data-valmsg-replace="true"></span>

In genere si usa dopo Validation Message Tag Helper un Input helper tag per la stessa proprietà. In questo modo è possibile visualizzare i messaggi di errore di convalida vicino all'input che ha causato l'errore.

Nota

È necessario avere una visualizzazione con i riferimenti agli script JavaScript e jQuery corretti per la convalida lato client. Per altre informazioni, vedere Convalida del modello.

Se si verifica un errore di convalida sul lato server, ad esempio quando la convalida sul lato server è personalizzata o quando la convalida sul lato client è disabilitata, MVC inserisce il messaggio di errore nel corpo dell'elemento <span>.

<span class="field-validation-error" data-valmsg-for="Email"
            data-valmsg-replace="true">
   The Email Address field is required.
</span>

Helper tag Validation Summary

  • Considera come destinazione gli elementi <div> con l'attributo asp-validation-summary

  • Helper HTML alternativo: @Html.ValidationSummary

Viene Validation Summary Tag Helper utilizzato per visualizzare un riepilogo dei messaggi di convalida. Il valore dell'attributo asp-validation-summary può corrispondere a uno dei valori seguenti:

asp-validation-summary Messaggi di convalida visualizzati
All Livello di modello e proprietà
ModelOnly Modello
None None

Esempio

Nell'esempio seguente il modello di dati ha DataAnnotation attributi, che genera messaggi di errore di convalida sull'elemento <input> . Quando si verifica un errore di convalida, l'helper tag di convalida visualizza il messaggio di errore:

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>
    Email:  <input asp-for="Email" /> <br />
    <span asp-validation-for="Email"></span><br />
    Password: <input asp-for="Password" /><br />
    <span asp-validation-for="Password"></span><br />
    <button type="submit">Register</button>
</form>

Codice HTML generato (se il modello è valido):

<form action="/DemoReg/Register" method="post">
  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"><br>
  <span class="field-validation-valid" data-valmsg-replace="true"
   data-valmsg-for="Email"></span><br>
  Password: <input name="Password" id="Password" type="password"
   data-val-required="The Password field is required." data-val="true"><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>

Helper tag Select

  • Genera l'elemento select e gli elementi option associati per le proprietà del modello.

  • Ha come helper HTML alternativi Html.DropDownListFor e Html.ListBoxFor

Select Tag Helperasp-for specifica il nome della proprietà di modello per l'elemento select e asp-items specifica gli elementi option. Ad esempio:

<select asp-for="Country" asp-items="Model.Countries"></select> 

Esempio:

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

Il metodo Index inizializza CountryViewModel, imposta il paese selezionato e lo passa alla visualizzazione Index.

public IActionResult Index()
{
    var model = new CountryViewModel();
    model.Country = "CA";
    return View(model);
}

Il metodo Index di HTTP POST visualizza la selezione:

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

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

Che genera il codice HTML seguente (con "CA" selezionato):

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

Nota

Non è consigliabile usare ViewBag o ViewData con l'helper tag Select. Un modello di visualizzazione è più solido e in genere presenta meno problemi quando si tratta di fornire metadati MVC.

Il valore dell'attributo asp-for rappresenta un caso speciale e non richiede un prefisso Model, che invece è richiesto dagli altri attributi di helper tag, ad esempio asp-items

<select asp-for="Country" asp-items="Model.Countries"></select> 

Associazione di enum

Spesso è comodo usare <select> con una proprietà enum e generare gli elementi SelectListItem dai valori enum.

Esempio:

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

Il metodo GetEnumSelectList genera un oggetto SelectList per 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>

È possibile contrassegnare l'elenco di enumeratori con l'attributo per ottenere un'interfaccia Display utente più completa:

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

Viene generato il codice HTML seguente:

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

Gruppo di opzioni

L'elemento optgroup> HTML <viene generato quando il modello di visualizzazione contiene uno o più SelectListGroup oggetti.

CountryViewModelGroup suddivide gli elementi SelectListItem nei gruppi "North America" ed "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; }

I due gruppi sono illustrati di seguito:

option group example

Codice HTML generato:

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

Selezione multipla

L'helper tag Select genera automaticamente l'attributo multiple = "multiple" se la proprietà specificata nell'attributo asp-for è IEnumerable. Dato, ad esempio, il modello seguente:

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

Con la visualizzazione seguente:

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

Viene generato il codice HTML seguente:

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

Nessuna selezione

Se si usa l'opzione "not specified" in più pagine, è possibile creare un modello per evitare di ripetere lo stesso codice HTML:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">
    @Html.EditorForModel()
    <br /><button type="submit">Register</button>
</form>

Il Views/Shared/EditorTemplates/CountryViewModel.cshtml modello:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">
    <option value="">--none--</option>
</select>

L'aggiunta di elementi di opzione> HTML <non è limitata al caso Nessuna selezione. La visualizzazione e il metodo di azione seguenti, ad esempio, generano codice HTML simile al codice precedente:

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="">&lt;none&gt;</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'elemento <option> corretto viene selezionato (con l'attributo selected="selected") a seconda del valore Country corrente.

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="">&lt;none&gt;</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>

Risorse aggiuntive