Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Хотя мы можем сами написать любой требуемый хелпер, но фреймворк MVC уже предоставляет большой набор встроенных html-хелперов, которые позволяют генерировать ту или иную разметку, главным образом, для работы с формами. Поэтому в большинстве случаев не придется создавать свои хелперы, и можно будет воспользоваться встроенными.
Для создания форм мы вполне можем использовать стандартные элементы html, например:
<form method="post" action="/Home/Buy"> <input type="hidden" value="@ViewBag.BookId" name="BookId" /> <table> <tr><td><p>Введите свое имя </p></td> <td><input type="text" name="Person" /> </td></tr> <tr><td><p>Введите адрес :</p></td> <td><input type="text" name="Address" /> </td></tr> <tr><td><input type="submit" value="Отправить" /> </td> <td></td></tr> </table> </form>
Это обычная html-форма, которая по нажатию на кнопку отправляет все введенные данные запросом POST на адрес /Home/Buy. Встроенный хелпер BeginForm/EndForm позволяет создать ту же самую форму:
@using(Html.BeginForm("Buy", "Home", FormMethod.Post)) { <input type="hidden" value="@ViewBag.BookId" name="BookId" /> <table> <tr><td><p>Введите свое имя </p></td> <td><input type="text" name="Person" /> </td></tr> <tr><td><p>Введите адрес :</p></td> <td><input type="text" name="Address" /> </td></tr> <tr><td><input type="submit" value="Отправить" /> </td> <td></td></tr> </table> }
Метод BeginForm принимает в качестве параметров имя метода действия и имя контроллера, а также тип запроса.
Данный хелпер создает как открывающий тег <form>
, так и закрывающий тег </form>
. Поэтому при рендеринге представления в
выходной поток у нас получится тот же самый html-код, что и с применением тега form. Поэтому оба способа идентичны.
Здесь есть один момент. Если у нас в контроллере определены две версии одного метода - для методов POST и GET, например:
[HttpGet] public ActionResult Buy() { return View(); } [HttpPost] public string Buy(Purchase purchase) { .............. return "Спасибо за покупку книги";; }
То есть фактически вызов страницы с формой и отправка формы осуществляется одним и тем же действием Buy. В этом случае можно не указывать в
хелпере Html.BeginForm
параметры:
@using(Html.BeginForm()) { ............. }
В предыдущем примере вместе с хелпером Html.BeginForm использовались стандартные элементы html. Однако набор html-хелперов содержит также хелперы для ввода информации пользователем. В MVC определен широкий набор хелперов ввода практически для каждого html-элемента. Что выбрать - хелпер или стандартный элементы ввода html, уже решает сам разработчик.
Вне зависимости от типа все базовые html-хелперы используют как минимум два параметра: первый параметр применяется для установки значений
для атрибутов id
и name
, а второй параметр - для установки значения атрибута value
Хелпер Html.TextBox
генерирует тег input
со значением атрибута type
равным text
.
Хелпер TextBox
используют для получения ввода пользователем информации. Так, перепишем предыдущую форму с заменой полей ввода на хелпер
Html.TextBox:
@using(Html.BeginForm("Buy", "Home", FormMethod.Post)) { <input type="hidden" value="@ViewBag.BookId" name="BookId" /> <p>Введите свое имя: </p> @Html.TextBox("Person", "Введите имя") <p>Введите адрес :</p> @Html.TextBox("Address", "Введите адрес") <p><input type="submit" value="Отправить" /></p> }
Мы получим тот же результат:
Хелпер TextArea
используется для создания элемента
<textarea>
, который представляет многострочное текстовое поле. Результатом выражения @Html.TextArea("text", "привет <br/> мир")
будет следующая html-разметка:
<textarea cols="20" id="text" name="text" rows="2">привет <br/> мир </textarea>
Обратите внимание, что хелпер декодирует помещаемое в него значение, в том числе и html-теги, (все хелперы декодируют значения моделей
и значения атрибутов). Другие версии хелпера TextArea
позволяют указать число строк и столбцов, определяющих размер текстового поля.
@Html.TextArea("text", "привет <br /> мир", 5, 50, null)
Этот хелпер сгенерирует следующую разметку:
<textarea cols="50" id="text" name="text" rows="5">привет <br /> мир </textarea>
В примере с формой мы использовали скрытое поле input type="hidden"
, вместо которого могли бы вполне использовать хелпер
Html.Hidden
. Так, следующий вызов хелпера:
@Html.Hidden("BookId", "2")
сгенерирует разметку:
<input id="BookId" name="BookId" type="hidden" value="2" />
А при передаче переменной из ViewBag нам надо привести ее к типу string: @Html.Hidden("BookId", @ViewBag.BookId as string)
Html.Password
создает поле для ввода пароля. Он похож на хелпер TextBox
, но вместо
введенных символов отображает маску пароля. Следующий код:
@Html.Password("UserPassword", "val")
генерирует разметку:
<input id="UserPassword" name="UserPassword" type="password" value="val" />
Для создания переключателей применяется хелпер Html.RadioButton
. Он генерирует элемент input
со значением type="radio"
.
Для создания группы переключателей, надо присвоить всем им одно и то же имя (свойство name
):
@Html.RadioButton("color", "red") <span>красный</span> <br /> @Html.RadioButton("color", "blue") <span>синий</span> <br /> @Html.RadioButton("color", "green", true) <span>зеленый</span>
Этот код создает следующую разметку:
<input id="color" name="color" type="radio" value="red" /> <span>красный</span> <br /> <input id="color" name="color" type="radio" value="blue" /> <span>синий</span> <br /> <input checked="checked" id="color" name="color" type="radio" value="green" /> <span>зеленый</span>
Html.CheckBox
может применяться для создания сразу двух элементов. Возьмем, к примеру, следующий код:
@Html.CheckBox("Enable", false)
Это выражение будет генерировать следующий HTML:
<input id="Enable" name="Enable" type="checkbox" value="true" /> <input name="Enable" type="hidden" value="false" />
То есть кроме собственно поля флажка, еще и генерируется скрытое поле. Зачем оно нужно? Дело в том, что браузер
посылает значение флажка только тогда, когда флажок выбран или отмечен. А скрытое поле гарантирует, что для элемента
Enable
будет установлено значение даже, если пользователь не отметил флажок.
Хелпер Html.Label
создает элемент <label/>
, а передаваемый в хелпер параметр определяет значение атрибута
for
и одновременно текст на элементе. Перегруженная версия хелпера позволяет определить значение атрибута for
и
текст на метке независимо друг от друга. Например, объявление хелпера Html.Label("Name")
создает следующую разметку:
<label for="Name">Name</label>
Элемент label
представляет простую метку, предназначенную для прикрепления информации к элементам ввода, например, к текстовым полям.
Атрибут for
элемента label
должен содержать ID ассоциированного элемента ввода. Если пользователь нажимает на
метку, то браузер автоматически передает фокус связанному с этой меткой элементу ввода.
Хелпер Html.DropDownList
создает выпадающий список, то есть элемент <select />
.
Для генерации такого списка нужна коллекция объектов SelectListItem
, которые представляют элементы списка.
Объект SelectListItem
имеет свойства Text
(отображаемый текст), Value
(само значение, которое может не
совпадать с текстом) и Selected
.
Можно создать коллекцию объектов SelectListItem
или использовать хелпер SelectList
. Этот хелпер просматривает объекты
IEnumerable
и преобразуют их в последовательность объектов SelectListItem
.
Так, код @Html.DropDownList("countires", new SelectList(new string[] {"Russia","USA", "Canada","France"}),"Countries")
генерирует следующую разметку:
<select id="countires" name="countires"><option value="">Countries</option> <option>Russia</option> <option>USA</option> <option>Canada</option> <option>France</option> </select>
Теперь более сложный пример. Выведем в список коллекцию элементов Book. В контроллере передадим этот список через ViewBag:
BookContext db = new BookContext(); public ActionResult Index() { SelectList books = new SelectList(db.Books, "Author", "Name"); ViewBag.Books = books; return View(); }
Здесь мы создаем объект SelectList, передавая в его конструктор набор значений для списка (db.Books), название свойства модели Book, которое будет использоваться в качестве значения (Author), и название свойства модели Book, которое будет использоваться для отображения в списке. В данном случае необязательно устанавливать два разных свойства, можно было и одно установить и для значения и отображения.
Тогда в представлении мы можем так использовать этот SelectList:
@Html.DropDownList("Author", ViewBag.Books as SelectList)
И при рендеринге представления все элементы SelectList добавятся в выпадающий список
Хелпер Html.ListBox
, также как и DropDownList
, создает элемент <select />
,
но при этом делает возможным множественное выделение элементов (то есть для атрибута multiple
устанавливается значение multiple
).
Для создания списка, поддерживающего множественное выделение, вместо SelectList
можно использовать класс MultiSelectList
:
@Html.ListBox("countires", new MultiSelectList(new string[] {"Россия","США", "Китай","Индия"}))
Этот код генерирует следующую разметку:
<select Length="9" id="countries" multiple="multiple" name="countires"> <option>Россия</option> <option>США</option> <option>Китай</option> <option>Индия</option> </select>
С передачей одиночных значений на сервер все понятно, но как передать множественные значения? Допустим, у нас есть следующая форма:
@using (Html.BeginForm()) { @Html.ListBox("countries", new MultiSelectList(new string[] { "Россия", "США", "Китай", "Индия" })) <p><input type="submit" value="Отправить" /></p> }
Тогда метод контроллера мог бы получать эти значения следующим образом:
[HttpPost] public string Index(string[] countries) { string result = ""; foreach (string c in countries) { result += c; result += ";"; } return "Вы выбрали: " + result; }
Как правило, на форме есть только одна кнопка для отправки. Однако в определенных ситуациях может возникнуть потребность, использовать более одной кнопки. Например, есть поле для ввода значения, а две кнопки указывают, надо это значение удалить или, наоборот, добавить:
@using (Html.BeginForm("MyAction", "Home", FormMethod.Post)) { <input type="text" name="product" /><br/> <button name="action" value="add">Добавить</button> <button name="action" value="delete">Удалить</button> }
Самое простое решение состоит в том, что для каждой кнопки устанавливается одинаковое значение атрибута name
, но разное для атрибута
value
. А метод, принимающий форму, может выглядеть следующим образом:
[HttpPost] public ActionResult MyAction(string product, string action) { if(action=="add") { } else if(action=="delete") { } // остальной код метода }
И с помощью условной конструкции в зависимости от значения параметра action, который хранит значение атрибута value нажатой кнопки, производятся определенные действия.