Partilhar via


Auxiliar de tags em formulários no ASP.NET Core

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

Este documento demonstra o trabalho com formulários e os elementos HTML comumente usados em um formulário. O elemento HTML Form fornece o mecanismo principal que os aplicativos Web usam para postar dados de volta no servidor. A maior parte deste documento descreve os Ajudantes de Tags e como eles podem ajudá-lo a criar formulários HTML robustos de forma produtiva. Recomendamos que leia Introdução aos Auxiliares de Etiquetas antes de ler este documento.

Em muitos casos, os Auxiliares de HTML fornecem uma abordagem alternativa para um Auxiliar de Tag específico, mas é importante reconhecer que os Auxiliares de Tag não substituem os Auxiliares de HTML e não há um Auxiliar de Tag para cada Auxiliar de HTML. Quando existe uma alternativa HTML Helper, ela é mencionada.

O auxiliar de tag de formulário

O Form Tag Helper:

  • Gera o valor do atributo HTML< FORM>action para uma ação do controlador MVC ou rota nomeada

  • Gera um Token de Verificação de Solicitação oculto para evitar falsificação de solicitação entre sites (quando usado com o [ValidateAntiForgeryToken] atributo no método de ação HTTP Post)

  • Fornece o asp-route-<Parameter Name> atributo, onde <Parameter Name> é adicionado aos valores de rota. Os parâmetros routeValues para Html.BeginForm e Html.BeginRouteForm fornecem funcionalidade semelhante.

  • Há uma alternativa de HTML Helper com Html.BeginForm e Html.BeginRouteForm

Exemplo:

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

O Form Tag Helper acima gera o seguinte HTML:

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

O tempo de execução do MVC gera o valor do atributo action a partir dos atributos de Form Tag Helper asp-controller e asp-action. O Auxiliar de Tag de Formulário também gera um Token de Verificação de Solicitação oculto para evitar ataques de falsificação de solicitação entre sites (quando usado com o atributo [ValidateAntiForgeryToken] no método de ação de HTTP Post). Proteger um formulário HTML puro contra falsificação de pedido entre sites é difícil. O Form Tag Helper fornece este serviço para si.

Usando uma rota nomeada

O asp-route atributo Tag Helper também pode gerar marcação para o atributo HTML action . Um aplicativo com uma rota nomeada register pode usar a seguinte marcação para a página de registro:

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

Muitas das visualizações na pasta Views/Account (geradas quando você cria um novo aplicativo Web com Contas Individuais) contêm o atributo asp-route-returnurl :

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

Observação

Com os modelos incorporados, returnUrl só é preenchido automaticamente quando tenta aceder a um recurso autorizado mas não está autenticado ou autorizado. Quando tenta um acesso não autorizado, o middleware de segurança redireciona-o para a página de início de sessão com o returnUrl definido.

O ajudante de marcação de ação do formulário

O Auxiliar de Tag de Ação de Formulário gera o atributo formaction na tag <button ...> ou <input type="image" ...> gerada. O formaction atributo controla onde um formulário envia seus dados. Ele se liga a <elementos de entrada> de tipo image e <elementos de botão> . O Form Action Tag Helper permite o uso de vários atributos AnchorTagHelperasp- para controlar qual formaction link é gerado para o elemento correspondente.

Atributos AnchorTagHelper suportados para controlar o valor de formaction:

Atributo Descrição
Controlador ASP O nome do controlador.
asp-ação O nome do método de ação.
Área ASP O nome da área.
página asp O nome da página Razor.
manipulador de página asp O nome do Razor controlador de página.
asp-rota O nome da rota.
asp-route-{valor} Um único valor de rota de URL. Por exemplo, asp-route-id="1234".
dados asp-all-route-data Todos os valores da rota.
ASP-fragmento O fragmento de URL.

Submeter exemplo ao controlador

A marcação a seguir envia o formulário para a Index ação de HomeController quando a entrada ou o botão são selecionados:

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

A marcação anterior gera o seguinte HTML:

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

Submeter para a página exemplo

A marcação a seguir envia o formulário para a AboutRazor Página:

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

A marcação anterior gera o seguinte HTML:

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

Enviar para exemplo de rota

Considere o /Home/Test endpoint.

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

A marcação a seguir submete o formulário para o /Home/Test endpoint.

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

A marcação anterior gera o seguinte HTML:

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

O auxiliar de tag de entrada

O Auxiliar de Marca de Entrada vincula um elemento HTML <input> a uma expressão de modelo na sua vista Razor.

Sintaxe:

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

O auxiliar de tag de entrada:

  • Gera os atributos HTML id e name para o nome da expressão especificado no atributo do asp-for. asp-for="Property1.Property2" é equivalente a m => m.Property1.Property2. O nome da expressão é o que é usado para o valor do asp-for atributo. Consulte a seção Nomes de expressões para obter informações adicionais.

  • Define o valor do atributo HTML type com base no tipo de modelo e nos atributos de anotação de dados aplicados à propriedade do modelo

  • Não sobrescreverá o valor do atributo HTML type quando um valor é especificado

  • Gera atributos de validação HTML5 a partir de atributos de anotação de dados aplicados às propriedades do modelo

  • Tem uma sobreposição no recurso HTML Helper com Html.TextBoxFor e Html.EditorFor. Consulte a seção HTML Helper alternatives to Input Tag Helper para obter detalhes.

  • Fornece digitação forte. Se o nome da propriedade mudar e você não atualizar o Auxiliar de tag, você receberá um erro semelhante ao seguinte:

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

O Input Auxiliar de Tag define o atributo HTML type com base no tipo .NET. A tabela a seguir lista alguns tipos .NET comuns e tipos HTML gerados (nem todos os tipos .NET estão listados).

Tipo .NET Tipo de entrada
Bool type="caixa de seleção"
Cordão type="texto"
Data e Hora type="datetime-local"
byte type="número"
int type="número"
Simples, Duplo type="número"

A tabela a seguir mostra alguns atributos comuns de anotações de dados que o auxiliar de tag de entrada mapeará para tipos de entrada específicos (nem todos os atributos de validação estão listados):

Atributo Tipo de entrada
[Endereço de e-mail] type="e-mail"
[Url] type="url"
[HiddenInput] type="oculto"
Telefone type="tel"
[DataType(DataType.Password)] type="senha"
[DataType(DataType.Date)] type="data"
[DataType(DataType.Time)] type="hora"

Exemplo:

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>

O código acima gera o seguinte HTML:

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

As anotações de dados aplicadas às Email propriedades e Password geram metadados no modelo. O Auxiliar de Tag de Entrada consome os metadados do modelo e produz atributos HTML5data-val-* (consulte Validação de modelo). Esses atributos descrevem os validadores a serem anexados aos campos de entrada. Isso fornece validação discreta de HTML5 e jQuery . Os atributos discretos têm o formato data-val-rule="Error Message", onde regra é o nome da regra de validação (como data-val-required, data-val-email, data-val-maxlength, etc.) Se uma mensagem de erro for fornecida no atributo, ela será exibida como o valor do data-val-rule atributo. Há também atributos do formulário data-val-ruleName-argumentName="argumentValue" que fornecem detalhes adicionais sobre a regra, por exemplo, data-val-maxlength-max="1024" .

Ao vincular vários input controles à mesma propriedade, os controles gerados compartilham o mesmo id, o que torna a marcação gerada inválida. Para evitar duplicações, especifique o id atributo para cada controle explicitamente.

Renderização de entrada oculta da caixa de seleção

As caixas de seleção em HTML5 não enviam um valor quando estão desmarcadas. Para permitir que um valor padrão seja enviado para uma caixa de seleção desmarcada, o Auxiliar de Tag de Entrada gera uma entrada oculta adicional para caixas de seleção.

Por exemplo, considere a seguinte Razor marcação que usa o Auxiliar de Tag de Entrada para uma propriedade IsCheckedde modelo booleano:

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

A marcação anterior Razor gera marcação HTML semelhante à seguinte:

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

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

A marcação HTML anterior mostra uma entrada oculta adicional com um nome de IsChecked e um valor de false. Por padrão, essa entrada oculta é processada no final do formulário. Quando o formulário é enviado:

  • Se a entrada da IsChecked caixa de seleção estiver marcada, ambos true e false são enviados como valores.
  • Se a entrada do checkbox IsChecked estiver desmarcada, somente o valor false de entrada oculto será submetido.

O processo de vinculação de modelo ASP.NET Core lê apenas o primeiro valor ao vincular a um valor bool, o que resulta em true para caixas de seleção marcadas e false para caixas de seleção desmarcadas.

Para configurar o comportamento da renderização de entrada oculta, defina a CheckBoxHiddenInputRenderMode propriedade em MvcViewOptions.HtmlHelperOptions. Por exemplo:

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

O código anterior desabilita a renderização de entrada oculta para caixas de seleção definindo CheckBoxHiddenInputRenderMode como CheckBoxHiddenInputRenderMode.None. Para todos os modos de renderização disponíveis, consulte o CheckBoxHiddenInputRenderMode enum.

Alternativas ao HTML Helper para o Input Tag Helper

Html.TextBox, Html.TextBoxFor, Html.Editor e Html.EditorFor têm funcionalidades que se sobrepõem ao Auxiliar de Tag de Entrada. O Auxiliar de Tag de Entrada definirá automaticamente o type atributo, Html.TextBox e Html.TextBoxFor não o fará. Html.Editor e Html.EditorFor lidam com coleções, objetos complexos e modelos; o Auxiliar de Tag de Entrada não. O Auxiliar de Tag de Entrada, Html.EditorFor e Html.TextBoxFor são fortemente tipados (usam expressões lambda); Html.TextBox e Html.Editor não são fortemente tipados (usam nomes de expressão).

HtmlAtributos

@Html.Editor() e @Html.EditorFor() usam uma entrada especial ViewDataDictionary chamada htmlAttributes ao executar os seus modelos padrão. Esse comportamento é opcionalmente aumentado usando additionalViewData parâmetros. A chave "htmlAttributes" não diferencia maiúsculas de minúsculas. A chave "htmlAttributes" é tratada de forma semelhante ao htmlAttributes objeto passado para auxiliares de entrada como @Html.TextBox().

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

Nomes de expressões

O valor do atributo asp-for é um ModelExpression, sendo parte do lado direito de uma expressão lambda. Portanto, asp-for="Property1" torna-se m => m.Property1 no código gerado e é por isso que você não precisa prefixar com Model. Você pode usar o caractere "@" para iniciar uma expressão embutida e mover-se antes do m.:

@{
  var joe = "Joe";
}

<input asp-for="@joe">

Gera o seguinte:

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

Com propriedades de coleção, asp-for="CollectionProperty[23].Member" gera o mesmo nome de asp-for="CollectionProperty[i].Member" quando i tem o valor 23.

Quando o ASP.NET Core MVC calcula o valor do ModelExpression, ele inspeciona várias fontes, incluindo ModelState. Considere <input type="text" asp-for="Name">. O atributo calculado value é o primeiro valor não nulo de:

  • ModelState entrada com a chave "Nome".
  • Resultado da expressão Model.Name.

Você também pode navegar até as propriedades filho usando o caminho da propriedade do modelo de exibição. Considere uma classe de modelo mais complexa que contém uma propriedade filho 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; }
}

No ponto de vista, vinculamo-nos a 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>

O seguinte HTML é gerado para Address.AddressLine1:

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

Nomes de expressões e coleções

Exemplo, um modelo que contém uma matriz de Colors:

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

    public int Age { get; set; }
}

O método de ação:

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

A seguir Razor mostra como você acessa um elemento específico 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>

O modelo Views/Shared/EditorTemplates/String.cshtml:

@model string

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

Amostra utilizando List<T>:

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

    public bool IsDone { get; set; }
}

A seguir Razor mostra como iterar sobre uma coleção:

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

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

foreach deve ser utilizado, se possível, quando o valor vai ser utilizado num asp-for contexto ou Html.DisplayFor equivalente. Em geral, for é melhor do que foreach (se o cenário permitir) porque não precisa alocar um enumerador, no entanto, avaliar um indexador em uma expressão LINQ pode ser caro e deve ser minimizado.

 

Observação

O código de exemplo comentado acima mostra como substituir a expressão lambda pelo operador @ para acessar cada ToDoItem na lista.

O auxiliar de tag textarea

O Textarea Tag Helper auxiliar de tag é semelhante ao Input Tag Helper.

  • Gera os atributos id e os atributos de validação de dados do modelo para um name.

  • Fornece digitação forte.

  • Alternativa ao HTML Helper: Html.TextAreaFor

Exemplo:

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>

O seguinte HTML é gerado:

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

Auxiliar de etiquetas

  • Gera a legenda e o atributo for num elemento <label> para um nome de expressão

  • Alternativa Assistente HTML: Html.LabelFor.

O Label Tag Helper fornece os seguintes benefícios sobre um elemento de rótulo HTML puro:

  • Você obtém automaticamente do atributo Display o valor do rótulo descritivo. O nome de exibição pretendido pode mudar ao longo do tempo, e a combinação do atributo Display e Auxiliar de Marca de Rótulo será aplicada Display em todos os lugares onde for utilizado.

  • Menos marcação no código-fonte

  • Digitação forte com a propriedade model.

Exemplo:

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>

O seguinte HTML é gerado para o <label> elemento :

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

O Label Tag Helper gerou o for valor do atributo "Email", que é o ID associado ao <input> elemento. Os Tag Helpers geram elementos consistentes id e for, para que possam ser corretamente associados. A legenda neste exemplo vem do Display atributo. Se o modelo não contivesse um Display atributo, a legenda seria o nome da propriedade da expressão. Para substituir a legenda padrão, adicione uma legenda dentro da tag de rótulo.

Os auxiliares de tag de validação

Existem dois Auxiliares de Tag de Validação. O Validation Message Tag Helper (que exibe uma mensagem de validação para uma única propriedade em seu modelo) e o Validation Summary Tag Helper (que exibe um resumo dos erros de validação). O Input Tag Helper adiciona atributos de validação do lado do cliente HTML5 a elementos de entrada com base em atributos de anotação de dados em suas classes de modelo. A validação também é realizada no servidor. O Auxiliar de Marca de Validação exibe essas mensagens de erro quando ocorre um erro de validação.

O Tag Helper de mensagem de validação

  • Adiciona o atributo HTML5data-valmsg-for="property" ao elemento span , que anexa as mensagens de erro de validação no campo de entrada da propriedade de modelo especificada. Quando ocorre um erro de validação do lado do cliente, o jQuery exibe a mensagem de <span> erro no elemento .

  • A validação também ocorre no servidor. Os clientes podem ter o JavaScript desativado e alguma validação só pode ser feita no lado do servidor.

  • Alternativa ao HTML Helper: Html.ValidationMessageFor

O Validation Message Tag Helper é usado com o asp-validation-for atributo em um elemento span HTML.

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

O Auxiliar de Etiqueta de Mensagem de Validação irá gerar o seguinte HTML:

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

Geralmente, utiliza o Validation Message Tag Helper após um Input Tag Helper para a mesma propriedade. Isso exibe todas as mensagens de erro de validação próximas à entrada que causou o erro.

Observação

Você deve ter uma visualização com as referências de script JavaScript e jQuery corretas para validação do lado do cliente. Consulte Validação de modelo para obter mais informações.

Quando ocorre um erro de validação do lado do servidor (por exemplo, quando a validação personalizada do lado do servidor ou a validação do lado do cliente está desativada), o <span> MVC coloca essa mensagem de erro como o corpo do elemento.

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

O auxiliar de tag de resumo de validação

  • Elementos de destino <div> com o asp-validation-summary atributo

  • Alternativa ao HTML Helper: @Html.ValidationSummary

O Validation Summary Tag Helper é usado para exibir um resumo das mensagens de validação. O asp-validation-summary valor do atributo pode ser qualquer um dos seguintes:

resumo de validação asp Mensagens de validação exibidas
All Nível de propriedade e modelo
ModelOnly Modelo
None Nenhum

Exemplo

No exemplo a seguir, o modelo de dados tem DataAnnotation atributos, o que gera mensagens de erro de validação no elemento <input>. Quando ocorre um erro de validação, o Auxiliar de Marca de Validação exibe a mensagem de erro:

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>

O HTML gerado (quando o modelo é válido):

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

O Auxiliar de Etiquetas de Seleção

  • Gera elementos select e option associados para as propriedades do seu modelo.

  • Há uma alternativa de HTML Helper com Html.DropDownListFor e Html.ListBoxFor

O Select Tag Helperasp-for especifica o nome da propriedade do modelo para o elemento select e asp-items especifica os elementos de opção . Por exemplo:

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

Exemplo:

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

O Index método inicializa o CountryViewModel, define o país selecionado e o passa para a Index exibição.

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

O método HTTP POST Index exibe a seleção:

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

A Index vista:

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

Que gera o seguinte HTML (com "CA" selecionado):

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

Observação

Não recomendamos o uso ViewBag ou ViewData com o Select Tag Helper. Um modelo de exibição é mais robusto no fornecimento de metadados MVC e, geralmente, menos problemático.

O valor do atributo asp-for é um caso especial e não requer um prefixo Model; os outros atributos do Auxiliar de Marcação (como asp-items) requerem.

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

Encadernação de enum

Muitas vezes é conveniente usar <select> com uma propriedade enum e gerar a partir dos valores SelectListItem os elementos enum.

Exemplo:

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

O GetEnumSelectList método gera um SelectList objeto para um 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>

Você pode marcar sua lista de enumeradores com o Display atributo para obter uma interface do usuário mais avançada:

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

O seguinte HTML é gerado:

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

Grupo de opções

O elemento HTML< optgroup> é gerado quando o modelo de exibição contém um ou mais SelectListGroup objetos.

Os CountryViewModelGroup agrupam os SelectListItem elementos nos grupos "América do Norte" e "Europa":

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

Os dois grupos são apresentados a seguir:

Exemplo de grupo de opções

O HTML gerado:

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

Seleção múltipla

O Select Tag Helper gerará automaticamente o atributo multiple = "multiple" se a propriedade especificada pelo atributo asp-for for um IEnumerable. Por exemplo, dado o seguinte modelo:

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

Com a seguinte vista:

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

Gera o seguinte HTML:

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

Sem seleção

Se você estiver usando a opção "não especificado" em várias páginas, você pode criar um modelo para eliminar a repetição do HTML:

@model CountryViewModel

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

O modelo Views/Shared/EditorTemplates/CountryViewModel.cshtml:

@model CountryViewModel

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

Adicionar <elementos> de opção HTML não está limitado ao caso de Sem seleção. Por exemplo, o seguinte método de exibição e ação gerará HTML semelhante ao código acima:

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>

O elemento correto <option> será selecionado (contém o selected="selected" atributo) dependendo do valor atual 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="">&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>

Recursos adicionais