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

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

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

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

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

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

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

  • Создает скрытый токен проверки запроса для предотвращения подделки межсайтовых запросов (при использовании с атрибутом в методе действия 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. Вспомогательная функция тега формы также создает скрытый токен проверки запроса для предотвращения подделки межсайтовых запросов (при использовании с атрибутом в методе действия HTTP Post). Защита чистой формы HTML от подделки межсайтовых запросов является трудной задачей, поэтому для ее решения используется вспомогательная функция тега формы.

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

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

<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 и элемента > . Вспомогательная функция тега действий формы позволяет использовать несколько атрибутов AnchorTagHelper для управления выходными данными ссылки formaction для соответствующего элемента.

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

attribute Описание
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>

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

Вспомогательная функция тега input привязывает элемент ввода > HTML к выражению модели в представлении Razor.

Синтаксис:

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

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

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

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

  • Значение атрибута 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"
Byte type="number"
Int type="number"
Single, Double type="number"

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

attribute Тип входных данных
[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">
    Email:  <input asp-for="Email" /> <br />
    Password: <input asp-for="Password" /><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, создающим метаданные для модели. Вспомогательная функция тега входных данных использует метаданные модели и создает атрибуты 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".

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

Флажки в 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 Core процесс привязки модели считывает только первое значение при привязке к bool значению, что приводит к true установлению флажков и снятию флажков false .

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

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

Предыдущий код отключает отрисовку скрытых входных значений для флажков, установив CheckBoxHiddenInputRenderMode для значение CheckBoxHiddenInputRenderMode.None . Сведения о всех доступных режимах рендеринга см. в разделе 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">
    Email:  <input asp-for="Email" /> <br />
    Password: <input asp-for="Password" /><br />
    Address: <input asp-for="Address.AddressLine1" /><br />
    <button type="submit">Register</button>
</form>

Следующий 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 и атрибуты проверки данных из модели для элемента id .

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

  • Располагает альтернативой вспомогательному методу 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 для элемента 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 в элементы входных данных на основе атрибутов заметок к данным в классах модели. Проверка также выполняется на сервере. Вспомогательная функция тега проверки отображает эти сообщения об ошибках при возникновении ошибки проверки.

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

  • Добавляет атрибут HTML5 в элемент span, который присоединяет сообщения об ошибках проверки к полю входных данных указанного свойства модели. При возникновении ошибки проверки на стороне клиента jQuery отображает сообщение об ошибке в элементе .

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

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

Validation Message Tag HelperИспользуется с asp-validation-for атрибутом в ЭЛЕМЕНТЕ Validation Message Tag Helper 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 HelperInput для того же свойства используется вспомогательная функция тега. В этом случае сообщения об ошибках проверки отображаются рядом с входными данными, вызвавшими ошибку.

Примечание

Для проверки на стороне клиента необходимо иметь представление с правильными ссылками на скрипты 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 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>
    Email:  <input asp-for="Email" /> <br />
    <span asp-validation-for="Email"></span><br />
    Password: <input asp-for="Password" /><br />
    <span asp-validation-for="Password"></span><br />
    <button type="submit">Register</button>
</form>

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

<form action="/DemoReg/Register" method="post">
  <div class="validation-summary-valid" data-valmsg-summary="true">
  <ul><li style="display:none"></li></ul></div>
  Email:  <input name="Email" id="Email" type="email" value=""
   data-val-required="The Email field is required."
   data-val-email="The Email field is not a valid email address."
   data-val="true"><br>
  <span class="field-validation-valid" data-valmsg-replace="true"
   data-valmsg-for="Email"></span><br>
  Password: <input name="Password" id="Password" type="password"
   data-val-required="The Password field is required." data-val="true"><br>
  <span class="field-validation-valid" data-valmsg-replace="true"
   data-valmsg-for="Password"></span><br>
  <button type="submit">Register</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

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

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

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

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

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

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

option group example

Созданный 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>

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

Вспомогательная функция выбора тега автоматически создаст атрибут Multiple = "Multiple" , если свойство, указанное в атрибуте, является 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.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>

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