Вспомогательные функции тегов в формах в ASP.NET Core

Авторы: Рик Андерсон (Rick Anderson), Н. Тейлор Маллен (N. Taylor Mullen), Дейв Пакетт (Dave Paquette) и Джерри Пелсер (Jerrie Pelser)

В этом документе приводятся сведения о работе с формами и элементами HTML, часто используемыми в формах. Элемент HTML форма предоставляет основной механизм, используемый веб-приложениями для отправки данных на сервер. В большей части этого документа описываются вспомогательные функции тегов и их применение для создания надежных форм HTML. Перед прочтением этого документа рекомендуется изучить статью Общие сведения о вспомогательных функциях тегов.

Во многих случаях вспомогательные методы HTML располагают альтернативными вариантами для определенной вспомогательной функции тега, но следует отметить, что вспомогательные функции тегов не заменяют вспомогательные методы HTML и для каждого вспомогательного метода HTML не существует конкретной вспомогательной функции тега. Если есть альтернатива вспомогательному методу HTML, она будет указана.

Вспомогательная функция тега формы

Вспомогательная функция тега формы:

  • Создает значение атрибута HTML <FORM> action для действия контроллера MVC или именованного маршрута

  • Создает скрытый токен проверки запроса для предотвращения подделки межсайтовых запросов (при использовании с атрибутом [ValidateAntiForgeryToken] в методе действия HTTP Post).

  • Предоставляет атрибут asp-route-<Parameter Name>, где <Parameter Name> добавляется в значения маршрута. Параметры routeValues для Html.BeginForm и Html.BeginRouteForm предоставления аналогичных функциональных возможностей.

  • Располагает альтернативой вспомогательному методу HTML — Html.BeginForm и Html.BeginRouteForm.

Пример:

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

Приведенная выше вспомогательная функция тега формы создает следующий код HTML:

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

Среда выполнения MVC генерирует значение атрибута action на основе атрибутов вспомогательной функции тега формы asp-controller и asp-action. Вспомогательная функция тега формы также создает скрытый токен проверки запроса для предотвращения подделки межсайтовых запросов (при использовании с атрибутом [ValidateAntiForgeryToken] в методе действия HTTP Post). Защита чистой формы HTML от подделки межсайтовых запросов является трудной задачей, поэтому для ее решения используется вспомогательная функция тега формы.

Использование именованного маршрута

Атрибут asp-route вспомогательной функции тега также может создавать разметку для атрибута HTML action. Приложение с маршрутом с именем register использует следующую разметку для страницы регистрации:

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

Многие представления в папке Views/Account (сформированные при создании веб-приложения с учетными записями отдельных пользователей) содержат атрибут asp-route-returnurl:

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

Примечание.

При использовании встроенных шаблонов returnUrl заполняется автоматически только в случае, если вы пытаетесь получить доступ к авторизованному ресурсу, но не прошли проверку подлинности или авторизацию. При попытке несанкционированного доступа ПО безопасности промежуточного слоя перенаправит вас на страницу входа с заданным returnUrl.

Вспомогательная функция тега действий формы

Вспомогательная функция тега действий формы создает атрибут formaction в созданном теге <button ...> или <input type="image" ...>. Атрибут formaction определяет, куда форма отправляет свои данные. Он привязывается к входным> элементам типа image и <элементам кнопки>.< Вспомогательная функция тега действий формы позволяет использовать несколько атрибутов asp- AnchorTagHelper для управления выходными данными ссылки formaction для соответствующего элемента.

Ниже перечислены поддерживаемые атрибуты AnchorTagHelper для управления значением formaction.

Атрибут Description
asp-controller Имя контроллера.
asp-action Имя метода действия.
asp-area Имя области.
asp-page Имя Razor страницы.
asp-page-handler Имя обработчика Razor страницы.
asp-route Имя маршрута.
asp-route-{value} Одно значение URL-адреса маршрута. Например, asp-route-id="1234".
asp-all-route-data Все значения маршрута.
asp-fragment Фрагмент URL-адреса.

Отправка формы в пример контроллера

Следующая разметка отправляет форму в действие Index, выполняемое HomeController, если выбран ввод или кнопка.

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

Предыдущая разметка создает следующий код HTML.

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

Отправка формы в пример страницы

Следующая разметка отправляет форму на страницу AboutRazor :

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

Предыдущая разметка создает следующий код HTML.

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

Отправка формы в пример маршрута

Рассмотрим конечную точку /Home/Test.

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

Следующая разметка отправляет форму в конечную точку /Home/Test.

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

Предыдущая разметка создает следующий код HTML.

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

Вспомогательная функция тега входных данных

Вспомогателя тегов ввода> ввода HTML <привязывается к выражению модели в представленииrazor.

Синтаксис

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

Вспомогательная функция тега входных данных:

  • Создает атрибуты HTML id и name для имени выражения, указанного в атрибуте asp-for. asp-for="Property1.Property2" эквивалентна m => m.Property1.Property2. Имя выражения совпадает со значением атрибута asp-for. Дополнительные сведения см. в разделе Имена выражений .

  • Задает значение атрибута HTML type на основе атрибутов типа модели и заметок к данным, примененным к свойству модели.

  • Значение атрибута HTML type не перезаписывается, если оно указано.

  • Создает атрибуты проверки HTML5 из атрибутов заметок к данным, примененным к свойствам модели.

  • Располагает перекрытием вспомогательного метода HTML с Html.TextBoxFor и Html.EditorFor. Дополнительные сведения см. в разделе Альтернативы вспомогательного метода HTML вспомогательной функции тега входных данных.

  • Обеспечивает строгую типизацию. Если после изменения имени свойства не выполнить обновление вспомогательной функции тега, возникнет ошибка следующего вида:

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

Вспомогательная функция тега Input задает атрибут HTML type на основе типа .NET. В следующей таблице перечислены некоторые распространенные типы .NET и созданный тип HTML (указаны не все типы .NET).

Тип .NET Тип ввода
Bool type="checkbox"
Строка type="text"
Дата/время type="datetime-local"
Байт type="number"
Int type="number"
Single, Double type="number"

В следующей таблице приведены некоторые наиболее распространенные атрибуты заметок к данным, которые вспомогательная функция тега входных данных будет сопоставлять с определенными типами входных данных (указаны не все атрибуты проверки):

Атрибут Тип ввода
[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"

Пример:

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>

Приведенный выше код создает следующий 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>

Заметки данных применяются к свойствам Email и Password, создающим метаданные для модели. Вспомогательная функция тега входных данных использует метаданные модели и создает атрибуты data-val-* HTML5 (см. статью о проверке модели). Эти атрибуты описывают проверяющие элементы управления, присоединяемые к полям входных данных. Это обеспечивает ненавязчивую проверку HTML5 и jQuery. Ненавязчивые атрибуты имеют формат data-val-rule="Error Message", где правило является именем правила проверки (например data-val-required, , data-val-email, data-val-maxlengthи т. д.). Если в атрибуте указано сообщение об ошибке, оно отображается в качестве значения атрибута data-val-rule . Также существуют атрибуты формы data-val-ruleName-argumentName="argumentValue", которые содержат дополнительные сведения о правиле, например data-val-maxlength-max="1024".

При привязке нескольких input элементов управления к одному свойству созданные элементы управления используют одинаковые idэлементы управления, что делает созданную разметку недопустимой. Чтобы предотвратить дубликаты, укажите id атрибут для каждого элемента управления явным образом.

Флажок скрытая отрисовка входных данных

Флажки в HTML5 не передают значение, если они сняты. Чтобы включить отправку значения по умолчанию для флажка без флажка, помощник по входным тегам создает дополнительные скрытые входные данные для флажков.

Например, рассмотрим следующую Razor разметку, которая использует вспомогательный элемент входного тега для логического свойства IsCheckedмодели:

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

Razor Предыдущая разметка создает разметку HTML, аналогичную следующей:

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

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

В приведенной выше разметке HTML показаны дополнительные скрытые входные данные с именем IsChecked и значением false. По умолчанию этот скрытый вход отображается в конце формы. При отправке формы:

  • IsChecked Если установлен флажок, true оба и false отправляются в виде значений.
  • IsChecked Если флажок не установлен, отправляется только скрытое входное значениеfalse.

Процесс привязки основных моделей ASP.NET считывает только первое значение при привязке к bool значению, что приводит к true флажкам флажков и false снятию флажков.

Чтобы настроить поведение скрытой отрисовки входных данных, задайте CheckBoxHiddenInputRenderMode для свойства значение MvcViewOptions.HtmlHelperOptions. Например:

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

Предыдущий код отключает скрытую отрисовку входных данных для флажков, установив для CheckBoxHiddenInputRenderMode.Noneпараметра CheckBoxHiddenInputRenderMode значение . Все доступные режимы отрисовки см. в перечислении CheckBoxHiddenInputRenderMode .

Альтернативы вспомогательного метода HTML вспомогательной функции тега входных данных

Html.TextBox, Html.TextBoxFor, Html.Editor и Html.EditorFor имеют функции, перекрывающиеся со вспомогательной функцией тега входных данных. Вспомогательная функция тега входных данных будет автоматически задавать атрибут type, а Html.TextBox и Html.TextBoxFor — нет. Html.Editor и Html.EditorFor обрабатывают коллекции, сложные объекты и шаблоны, а вспомогательная функция тега входных данных не делает этого. Вспомогатель Html.EditorFor тега ввода и Html.TextBoxFor строго типизирован (они используют лямбда-выражения) Html.TextBox и Html.Editor не являются (они используют имена выражений).

HtmlAttributes

При выполнении шаблонов по умолчанию @Html.Editor() и @Html.EditorFor() используют специальную запись ViewDataDictionary с именем htmlAttributes. Это поведение дополняется параметрами additionalViewData. Ключ "htmlAttributes" не учитывает регистр. Ключ "htmlAttributes" обрабатывается так же, как htmlAttributes объект, передаваемый во вспомогательные функции входных данных, такие как @Html.TextBox().

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

Имена выражений

Значением атрибута asp-for является ModelExpression и правая часть лямбда-выражения. Таким образом, asp-for="Property1" становится m => m.Property1 в созданном коде, поэтому нет необходимости добавлять префикс Model. Чтобы начать встроенное выражение и переместить перед m., используется символ "@":

@{
  var joe = "Joe";
}

<input asp-for="@joe">

Выводится следующий результат:

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

При использовании свойств коллекции asp-for="CollectionProperty[23].Member" генерирует то же самое имя, что и asp-for="CollectionProperty[i].Member", если i имеет значение 23.

Когда MVC ASP.NET Core рассчитывает значение ModelExpression, он оценивает несколько источников, включая ModelState. Вы можете использовать <input type="text" asp-for="Name">. Рассчитанный атрибут value является первым значением, отличным от NULL, из:

  • записи ModelState с ключом "Name";
  • результата выражения Model.Name.

Для перехода к дочерним свойствам можно также использовать путь к свойству модели представления. Рассмотрим более сложный класс модели, который содержит дочернее свойство 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; }
}

В представлении выполняется привязка к 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>

Следующий HTML создан для Address.AddressLine1:

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

Имена выражений и коллекций

Пример модели, содержащей массив Colors:

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

    public int Age { get; set; }
}

Метод действия:

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

Razor Ниже показано, как получить доступ к конкретному 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>

Шаблон Views/Shared/EditorTemplates/String.cshtml :

@model string

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

Пример с использованием List<T>:

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

    public bool IsDone { get; set; }
}

Razor Ниже показано, как выполнить итерацию по коллекции:

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

Шаблон 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, когда значение будет применяться в эквивалентном контексте asp-for или Html.DisplayFor. Обычно лучше использовать for, чем foreach (если сценарий позволяет), так как ему не нужно выделять перечислитель. Тем не менее оценка индексатора в выражении LINQ может быть недешевой, поэтому ее нужно минимизировать.

 

Примечание.

В приведенном выше комментированном коде показано, как заменить лямбда-выражение оператором @, чтобы получить доступ к каждому ToDoItem в списке.

Вспомогательная функция тега Textarea

Вспомогательная функция тега Textarea Tag Helperаналогична вспомогательной функции тега входных данных.

  • id Создает атрибуты и name атрибуты проверки данных из модели для <элемента textarea>.

  • Обеспечивает строгую типизацию.

  • Располагает альтернативой вспомогательному методу HTML — Html.TextAreaFor.

Пример:

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>

Создается следующий HTML:

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

Вспомогательная функция тега метки

  • Создает подпись for и атрибут метки в элементе <метки> для имени выражения.

  • Располагает альтернативой вспомогательному методу HTML — Html.LabelFor.

Предоставляет Label Tag Helper следующие преимущества для чистого элемента метки HTML:

  • Вы автоматически получаете значение описательной метки из Display атрибута. Предполагаемое отображаемое имя может изменяться с течением времени, а сочетание атрибута Display и вспомогательной функции тега метки будет применять атрибут Display везде, где он используется.

  • Меньше разметки в исходном коде.

  • Строгая типизация со свойством модели.

Пример:

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>

Для элемента <label> создан следующий HTML:

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

Вспомогательная функция тега метки сгенерировала для атрибута for значение "Email", представляющее собой идентификатор, связанный с элементом <input>. Вспомогательные функции тегов создают согласованные элементы id и for, чтобы обеспечить их правильное связывание. Заголовок в этом примере взят из атрибута Display. Если модель не содержит атрибут Display, заголовком будет имя свойства выражения. Чтобы переопределить подпись по умолчанию, добавьте подпись внутри тега метки.

Вспомогательные функции тегов проверки

Существует две вспомогательные функции тегов проверки. Validation Message Tag Helper отображает сообщение проверки для одного свойства в модели, Validation Summary Tag Helper отображает сводку ошибок проверки. Input Tag Helper добавляет клиентские атрибуты проверки HTML5 в элементы входных данных на основе атрибутов заметок к данным в классах модели. Проверка также выполняется на сервере. Вспомогательная функция тега проверки отображает эти сообщения об ошибках при возникновении ошибки проверки.

Вспомогательная функция тега сообщения о проверке

  • Добавляет атрибут data-valmsg-for="property" HTML5 в элемент span, который присоединяет сообщения об ошибках проверки к полю входных данных указанного свойства модели. При возникновении ошибки проверки на стороне клиента jQuery отображает сообщение об ошибке в элементе <span>.

  • Проверка также выполняется на сервере. На клиентах может быть отключена поддержка JavaScript, поэтому некоторые проверки выполняются только на стороне сервера.

  • Располагает альтернативой вспомогательному методу HTML — Html.ValidationMessageFor.

Используется Validation Message Tag Helper с атрибутом asp-validation-for в элементе диапазона HTML.

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

Вспомогательная функция тега сообщения о проверке создает следующий HTML:

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

Обычно для того же свойства используется вспомогательный Validation Message Tag Helper Input тег. В этом случае сообщения об ошибках проверки отображаются рядом с входными данными, вызвавшими ошибку.

Примечание.

Для проверки на стороне клиента необходимо иметь представление с правильными ссылками на скрипты JavaScript и jQuery. Дополнительные сведения см. в статье о проверке модели.

При возникновении ошибки проверки на стороне сервера (например, если выполняется пользовательская проверка на стороне сервера или проверка на стороне клиент отключена) MVC размещает сообщение об ошибке в тексте элемента <span>.

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

Вспомогательная функция тега сводки по проверке

  • Работает с элементами <div>, имеющими атрибут asp-validation-summary.

  • Располагает альтернативой вспомогательному методу HTML — @Html.ValidationSummary.

Используется Validation Summary Tag Helper для отображения сводки сообщений проверки. Значением атрибута asp-validation-summary может быть любое из следующих:

asp-validation-summary Отображаемые сообщения о проверке
All Свойство и уровень модели
ModelOnly Модель
None нет

Пример

В следующем примере модель данных имеет атрибуты DataAnnotation, в результате чего создаются сообщения об ошибках проверки для элемента <input>. При возникновении ошибки проверки вспомогательная функция тега проверки отображает следующее сообщение об ошибке:

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>

Созданный HTML (если модель является допустимой):

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

Вспомогательная функция тега Select

  • Создает элемент select и связанные элементы option для свойств модели.

  • Располагает альтернативой вспомогательному методу HTML — Html.DropDownListFor и Html.ListBoxFor.

Select Tag Helper asp-for указывает имя свойства модели для элемента select, а asp-items указывает элементы option. Например:

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

Пример:

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

Метод Index инициализирует CountryViewModel, задает выбранную страну и передает их в представление Index.

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

Метод HTTP POST Index отображает выбор:

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

Представление 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>

Создается следующий HTML (с выбранным значением "CA"):

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

Примечание.

С вспомогательной функцией тега Select не рекомендуется использовать ViewBag или ViewData. Модель представления более надежна в процессе предоставления метаданных MVC и, как правило, менее проблематична.

Значение атрибута asp-for является особым случаем и не требует префикса Model, тогда как он необходим другим атрибутам вспомогательной функции тега (например, asp-items).

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

Привязка перечисления

Часто бывает удобно использовать <select> со свойством enum и создавать элементы SelectListItem из значений enum.

Пример:

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

Метод GetEnumSelectList создает объект SelectList для перечисления.

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

Список перечислителя можно пометить атрибутом Display для формирования пользовательского интерфейса с более широкими функциональными возможностями:

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

Создается следующий HTML:

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

Группа параметров

Элемент html <optgroup> создается, когда модель представления содержит один или несколько SelectListGroup объектов.

CountryViewModelGroup группирует элементы SelectListItem в группы "North America" и "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; }

Ниже приведены две группы:

пример группы параметров

Созданный HTML:

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

Множественный выбор

Вспомогательная функция Select автоматически создаст атрибут multiple = "multiple", если свойство, указанное в атрибуте asp-for, имеет значение IEnumerable. Допустим, имеется такая модель:

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

Со следующим представлением:

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

Генерирует следующий 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>

Нет выделенных элементов

Если вы используете параметр "not specified" (не выбрано) на нескольких страницах, можно создать шаблон, чтобы исключить повторяющийся HTML:

@model CountryViewModel

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

Шаблон Views/Shared/EditorTemplates/CountryViewModel.cshtml :

@model CountryViewModel

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

Добавление элементов параметра> HTML <не ограничивается вариантом "Нет выбора". Например, следующее представление и метод действия создадут HTML, аналогичный приведенному выше коду:

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>

В зависимости от текущего значения Country будет выбран соответствующий элемент <option> (содержащий атрибут selected="selected").

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>

Дополнительные ресурсы