Auxiliares de marca em formulários no ASP.NET Core
De Rick Anderson, N. Taylor Mullen, Dave Paquette e Jerrie Pelser
Este documento demonstra como é o trabalho com Formulários e os elementos HTML usados comumente em um Formulário. O elemento HTML Formulário fornece o mecanismo primário que os aplicativos Web usam para postar dados para o servidor. A maior parte deste documento descreve os Auxiliares de marca e como eles podem ajudar você a criar formulários HTML robustos de forma produtiva. É recomendável que você leia Introdução ao auxiliares de marca antes de ler este documento.
Em muitos casos, os Auxiliares HTML fornecem uma abordagem alternativa a um Auxiliar de Marca específico, mas é importante reconhecer que os Auxiliares de Marca não substituem os Auxiliares HTML e que não há um Auxiliar de Marca para cada Auxiliar HTML. Quando existe um Auxiliar HTML alternativo, ele é mencionado.
O Auxiliar de marca de formulário
O Auxiliar de Marca de Formulário:
Gera o valor do atributo HTML <FORM>
action
valor de atributo para uma ação de controlador MVC ou rota nomeadaGera um Token de verificação de solicitação oculto para evitar a falsificação de solicitações entre sites (quando usado com o atributo
[ValidateAntiForgeryToken]
no método de ação HTTP Post)Fornece o atributo
asp-route-<Parameter Name>
, em que<Parameter Name>
é adicionado aos valores de rota. Os parâmetrosrouteValues
paraHtml.BeginForm
eHtml.BeginRouteForm
fornecem funcionalidade semelhante.Tem uma alternativa de Auxiliar HTML
Html.BeginForm
eHtml.BeginRouteForm
Exemplo:
<form asp-controller="Demo" asp-action="Register" method="post">
<!-- Input and Submit elements -->
</form>
O Auxiliar de marca de formulário acima gera o HTML a seguir:
<form method="post" action="/Demo/Register">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>
O runtime do MVC gera o valor do atributo action
dos atributos asp-controller
e asp-action
do Auxiliar de marca de formulário. O Auxiliar de marca de formulário também gera um Token de verificação de solicitação oculto para evitar a falsificação de solicitações entre sites (quando usado com o atributo [ValidateAntiForgeryToken]
no método de ação HTTP Post). É difícil proteger um Formulário HTML puro contra falsificação de solicitações entre sites e o Auxiliar de marca de formulário fornece este serviço para você.
Usando uma rota nomeada
O atributo do Auxiliar de Marca asp-route
também pode gerar a marcação para o atributo HTML action
. Um aplicativo com uma rota chamada register
poderia usar a seguinte marcação para a página de registro:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>
Muitas das exibições na pasta Modos de Exibição/Conta (gerada quando você cria um novo aplicativo Web com Contas de usuário 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 internos, returnUrl
só é preenchido automaticamente quando você tenta acessar um recurso autorizado, mas não está autenticado ou autorizado. Quando você tenta fazer um acesso não autorizado, o middleware de segurança o redireciona para a página de logon com o returnUrl
definido.
Auxiliar de Marcação de Ação de Formulário
O Auxiliar de Marcação de Ação de Formulário gera o atributo formaction
na marcação <button ...>
ou <input type="image" ...>
gerada. O atributo formaction
controla onde um formulário envia seus dados. Ele se associa à elementos de <entrada> do tipo image
e elementos de <botão>. O Auxiliar de Marca de Ação de Formulário permite o uso de vários atributos do AnchorTagHelper asp-
para controlar qual formaction
link é gerado para o elemento correspondente.
Atributos AnchorTagHelper com suporte para controlar o valor de formaction
:
Atributo | Descrição |
---|---|
asp-controller | O nome do controlador. |
asp-action | O nome do método da ação. |
asp-area | O nome da área. |
asp-page | O nome da página Razor. |
asp-page-handler | O nome do manipulador da página doRazor. |
asp-route | O nome da rota. |
asp-route-{value} | Um único valor de rota de URL. Por exemplo, asp-route-id="1234" . |
asp-all-route-data | Todos os valores de rota. |
asp-fragment | O fragmento de URL. |
Exemplo de Enviar ao controlador
A marcação a seguir envia o formulário à ação Index
de HomeController
quando a entrada ou botão são escolhidos:
<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>
Exemplo de Enviar a uma página
A marcação a seguir envia o formulário para a Página About
Razor:
<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>
Exemplo de Enviar a uma rota
Considere o ponto de extremidade /Home/Test
:
public class HomeController : Controller
{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}
A marcação a seguir envia o formulário ao ponto de extremidade /Home/Test
.
<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 marca de entrada
O Auxiliar de Marca de Entrada associa um elemento de <entrada> HTML a uma expressão de modelo na sua exibição do razor.
Sintaxe:
<input asp-for="<Expression Name>">
O auxiliar de marca de entrada:
Gera os atributos HTML
id
ename
para o nome da expressão especificada no atributoasp-for
.asp-for="Property1.Property2"
é equivalente am => m.Property1.Property2
. O nome da expressão é o que é usado para o valor do atributoasp-for
. Consulte a seção Nomes de expressão para obter informações adicionais.Define o valor do atributo HTML
type
com base no de tipo de modelo e em atributos de anotação de dados aplicados à propriedade de modeloO valor do atributo HTML
type
não será substituído quando um for especificadoGera atributos de validação HTML5 de atributos de anotação de dados aplicados a propriedades de modelo
Tem uma sobreposição de recursos de Auxiliar HTML com
Html.TextBoxFor
eHtml.EditorFor
. Consulte a seção Alternativas de Auxiliar HTML ao Auxiliar de marca de entrada para obter detalhes.Fornece tipagem forte. Se o nome da propriedade for alterado e você não atualizar o Auxiliar de marca, você verá 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 Auxiliar de marca Input
define o atributo HTML type
com base no tipo .NET. A tabela a seguir lista alguns tipos .NET comuns e o tipo HTML gerado (não estão listados todos os tipos .NET).
Tipo .NET | Tipo de entrada |
---|---|
Bool | type="checkbox" |
String | type="text" |
Datetime | type="datetime-local" |
Byte | type="number" |
int | type="number" |
Single e Double | type="number" |
A tabela a seguir mostra alguns atributos de anotações de dados comuns que o auxiliar de marca de entrada mapeará para tipos de entrada específicos (não são listados todos os atributos de validação):
Atributo | Tipo de entrada |
---|---|
[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" |
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 propriedades Email
e Password
geram metadados no modelo. O Auxiliar de Marca de Entrada consome os metadados do modelo e produz atributos HTML5 data-val-*
(veja Validação de Modelo). Esses atributos descrevem os validadores a serem anexados aos campos de entrada. Isso fornece validação de jQuery e HTML5 discreto. Os atributos não discretos têm o formato data-val-rule="Error Message"
, em que 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 atributo data-val-rule
. Também há atributos do formulário data-val-ruleName-argumentName="argumentValue"
que fornecem detalhes adicionais sobre a regra, por exemplo, data-val-maxlength-max="1024"
.
Ao associar vários controles do input
à mesma propriedade, os controles gerados compartilham o mesmo id
, o que torna a marcação gerada inválida. Para evitar duplicatas, especifique o atributo id
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 habilitar um valor padrão a ser enviado para uma caixa de seleção desmarcada, o Auxiliar de Marca de Entrada gera uma entrada oculta adicional para caixas de seleção.
Por exemplo, considere a marcação Razor a seguir que usa o Auxiliar de Marca de Entrada para uma propriedade de modelo booliano IsChecked
:
<form method="post">
<input asp-for="@Model.IsChecked" />
<button type="submit">Submit</button>
</form>
A marcação Razor anterior 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 é renderizada no final do formulário. Quando o formulário é enviado:
- Se a entrada da
IsChecked
caixa de seleção for marcada,true
efalse
serão enviadas como valores. - Se a entrada da caixa de seleção
IsChecked
estiver desmarcada, somente o valorfalse
de entrada oculto será enviado.
O processo de associação de modelo do ASP.NET Core lê apenas o primeiro valor ao associar 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 propriedade CheckBoxHiddenInputRenderMode 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 a enumeração CheckBoxHiddenInputRenderMode.
Alternativas de Auxiliar HTML ao Auxiliar de marca de entrada
Html.TextBox
, Html.TextBoxFor
, Html.Editor
e Html.EditorFor
têm recursos que se sobrepõem aos di Auxiliar de marca de entrada. O Auxiliar de marca de entrada define automaticamente o atributo type
; Html.TextBox
e Html.TextBoxFor
não o fazem. Html.Editor
e Html.EditorFor
manipulam coleções, objetos complexos e modelos; o Auxiliar de marca de entrada não o faz. O Auxiliar de marca de entrada Html.EditorFor
e Html.TextBoxFor
são fortemente tipados (eles usam expressões lambda); Html.TextBox
e Html.Editor
não usam (eles usam nomes de expressão).
HtmlAttributes
@Html.Editor()
e @Html.EditorFor()
usam uma entrada ViewDataDictionary
especial chamada htmlAttributes
ao executar seus modelos padrão. Esse comportamento pode ser aumentado usando parâmetros additionalViewData
. A chave "htmlAttributes" diferencia maiúsculas de minúsculas. A chave "htmlAttributes" é tratada de forma semelhante ao objeto htmlAttributes
passado para auxiliares de entrada como @Html.TextBox()
.
@Html.EditorFor(model => model.YourProperty,
new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })
Nomes de expressão
O valor do atributo asp-for
é um ModelExpression
e o lado direito de uma expressão lambda. Portanto, asp-for="Property1"
se torna m => m.Property1
no código gerado e é por isso você não precisa colocar o prefixo Model
. Você pode usar o caractere "@" para iniciar uma expressão embutida e mover para antes de 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 que asp-for="CollectionProperty[i].Member"
quando i
tem o valor 23
.
Quando o ASP.NET Core MVC calcula o valor de ModelExpression
, ele inspeciona várias fontes, inclusive o ModelState
. Considere o <input type="text" asp-for="Name">
. O atributo value
calculado é o primeiro valor não nulo:
- Da entrada de
ModelState
com a chave "Name". - Do resultado da expressão
Model.Name
.
Navegando para propriedades filho
Você também pode navegar para propriedades filho usando o caminho da propriedade do modelo de exibição. Considere uma classe de modelo mais complexa que contém uma propriedade Address
filho.
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; }
}
Na exibição, associamos 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 HTML a seguir é gerado para Address.AddressLine1
:
<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">
Nomes de expressão 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));
}
O Razor a seguir mostra como você acessa um elemento Color
específico:
@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 />
Exemplo usando List<T>
:
public class ToDoItem
{
public string Name { get; set; }
public bool IsDone { get; set; }
}
O Razor a seguir mostra como iterar em 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 usado, se possível, quando o valor está prestes a ser usado em um contexto equivalente asp-for
ou Html.DisplayFor
. Em geral, for
é melhor do que foreach
(se o cenário permitir) porque não é necessário alocar um enumerador; no entanto, avaliar um indexador em uma expressão LINQ pode ser caro, o que deve ser minimizado.
Observação
O código de exemplo comentado acima mostra como você substituiria a expressão lambda pelo operador @
para acessar cada ToDoItem
na lista.
Auxiliar de marca de área de texto
O auxiliar de marca Textarea Tag Helper
é semelhante ao Auxiliar de marca de entrada.
Gera os atributos
id
ename
, bem como os atributos de validação de dados do modelo para um elemento <textarea>.Fornece tipagem forte.
Alternativa de Auxiliar HTML:
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 HTML a seguir é 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 '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>
O auxiliar de marca de rótulo
Gera a legenda do rótulo e o atributo
for
em um elemento <rótulo> para um nome de expressãoAlternativa de Auxiliar HTML:
Html.LabelFor
.
O Label Tag Helper
fornece os seguintes benefícios em comparação com um elemento de rótulo HTML puro:
Você obtém automaticamente o valor do rótulo descritivo do atributo
Display
. O nome de exibição desejado pode mudar com o tempo e a combinação do atributoDisplay
e do Auxiliar de Marca de Rótulo aplicaráDisplay
em qualquer lugar em que for usado.Menos marcação no código-fonte
Tipagem forte com a propriedade de modelo.
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 HTML a seguir é gerado para o elemento <label>
:
<label for="Email">Email Address</label>
O Auxiliar de marca de rótulo gerou o valor do atributo for
de "Email", que é a ID associada ao elemento <input>
. Auxiliares de marca geram elementos id
e for
consistentes para que eles possam ser associados corretamente. A legenda neste exemplo é proveniente do atributo Display
. Se o modelo não contivesse um atributo Display
, a legenda seria o nome da propriedade da expressão. Para substituir a legenda padrão, adicione um legenda dentro da marca de rótulo.
Os auxiliares de marca de validação
Há dois auxiliares de marca 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 para elementos de entrada baseados em atributos de anotação de dados em suas classes de modelo. A validação também é executada no servidor. O Auxiliar de marca de validação exibe essas mensagens de erro quando ocorre um erro de validação.
O Auxiliar de marca de mensagem de validação
Adiciona o atributo HTML5
data-valmsg-for="property"
ao elemento span, que anexa as mensagens de erro de validação ao campo de entrada da propriedade de modelo especificada. Quando ocorre um erro de validação do lado do cliente, jQuery exibe a mensagem de erro no elemento<span>
.A validação também é feita no servidor. Os clientes poderão ter o JavaScript desabilitado e parte da validação só pode ser feita no lado do servidor.
Alternativa de Auxiliar HTML:
Html.ValidationMessageFor
O Validation Message Tag Helper
é usado com o atributo asp-validation-for
em um elemento HTML span.
<span asp-validation-for="Email"></span>
O Auxiliar de marca de mensagem de validação gerará o HTML a seguir:
<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true"></span>
Geralmente, você usa o Validation Message Tag Helper
após um Auxiliar de Marca Input
para a mesma propriedade. Fazer isso exibe as mensagens de erro de validação próximo à entrada que causou o erro.
Observação
É necessário ter uma exibição com as referências de script jQuery e JavaScript corretas em vigor para a 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 você tem validação do lado do servidor personalizada ou a validação do lado do cliente está desabilitada), o MVC coloca essa mensagem de erro como o corpo do elemento <span>
.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>
Auxiliar de marca de resumo de validação
Tem como alvo elementos
<div>
com o atributoasp-validation-summary
Alternativa de Auxiliar HTML:
@Html.ValidationSummary
O Validation Summary Tag Helper
é usado para exibir um resumo das mensagens de validação. O valor do atributo asp-validation-summary
pode ser qualquer um dos seguintes:
asp-validation-summary | Mensagens de validação exibidas |
---|---|
All |
Nível da propriedade e do modelo |
ModelOnly |
Modelar |
None |
Nenhum |
Amostra
No exemplo a seguir, o modelo de dados é decorado com atributos DataAnnotation
, 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 código 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>
Auxiliar de Marca de Seleção
Gera select e os elementos option associados para as propriedades do modelo.
Tem uma alternativa de Auxiliar HTML
Html.DropDownListFor
eHtml.ListBoxFor
O atributo Select Tag Helper
asp-for
especifica o nome da propriedade do modelo para o elemento selecionar e asp-items
especifica os elementos 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 método Index
inicializa o CountryViewModel
, define o país selecionado e o transmite para a exibição Index
.
public IActionResult Index()
{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}
O método Index
HTTP POST 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 exibição 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>
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 é recomendável usar ViewBag
ou ViewData
com o Auxiliar de Marca de Seleção. Um modelo de exibição é mais robusto para fornecer 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 requerem (como asp-items
)
<select asp-for="Country" asp-items="Model.Countries"></select>
Associação de enumeração
Geralmente, é conveniente usar <select>
com uma propriedade enum
e gerar os elementos SelectListItem
dos valores 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 método GetEnumSelectList
gera um objeto SelectList
para uma enumeração.
@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>
É possível decorar sua lista de enumeradores com o atributo Display
para obter uma interface do usuário mais rica:
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 HTML a seguir é 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 objetos SelectListGroup
.
O CountryViewModelGroup
agrupa os elementos SelectListItem
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 mostrados abaixo:
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 Auxiliar de Marca de Seleção gerará automaticamente o atributo multiple = "multiple" se a propriedade especificada no atributo asp-for
for um IEnumerable
. Por exemplo, considerando 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 exibição:
@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>
Nenhuma seleção
Se acabar usando a opção "não especificado" em várias páginas, você poderá criar um modelo para eliminar o HTML de repetição:
@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>
O acréscimo de elementos HTML <option> não está limitado ao caso de No selection. Por exemplo, o seguinte método de ação e exibição gerarão 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=""><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>
O elemento <option>
correto será selecionado (contém o atributo selected="selected"
) dependendo do valor atual 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>