Содержание
При разработке приложений в ASP.NET Core MVC активно используются различные веб-формы — форма регистрации нового пользователя, входа в систему, загрузки файлов на сервер и прочие и нам важно, чтобы данные, которые пользователь отправляет нам через форму корректно обрабатывались контроллером.
Получение контроллером данных из формы можно организовать разными способами, в зависимости от наших потребностей. При этом, в ASP.NET Core MVC для получения данных формы действуют те же правила, что и при получении данных из строки запроса, что значительно облегчает нам изучение этой темы.
Тестовое приложение
Так как мы пока ещё не знаем ничего про представления (View) в ASP.NET Core MVC, то наше тестовое приложение будет пока работать с обычным html-файлом, содержащим веб-формы с разным содержимым. Создадим новый проект ASP.NET Core MVC и добавим в папку wwwroot
файл data.html
со следующим содержимым:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Работа с формами в ASP.NET Core</title> </head> <body> <h3>Передача примитивных типов</h3> <form method='post' action='Form/GetPrimitive'> <label>Имя:</label><br /> <input name='name' /><br /> <label>Возраст:</label><br /> <input type='number' name='age' /><br /> <input type='submit' value='Отправить' /> </form> </body> </html>
В этом файле пока определена одна форма с помощью которой пользователь будет отправлять методом POST имя и возраст человека.
Также добавим в папку Controllers новый котроллер — FormController
и определим в нем следующее действие:
using Microsoft.AspNetCore.Mvc; namespace FirstMvcSite.Controllers { public class FormController : Controller { public async Task Index() { HttpContext.Response.ContentType = "text/html"; await HttpContext.Response.SendFileAsync(@"wwwroot\data.html"); } } }
Здесь в методе Index()
мы отправляем пользователю файл data.html и, чтобы он отображался в браузере именно как html-страница — устанавливаем заголовок Content-Type:
HttpContext.Response.ContentType = "text/html";
В дальнейшем мы продолжим дописывать файл data.html, а пока разберемся более детально с кодом веб-формы:
<form method='post' action='Form/GetPrimitive'>
в этом тэге мы видим, что для отправки данных будет использоваться метод POST
, и запрос отправится по пути «Form/GetPrimitive
«, т.е. в контроллер, который будет загружать файл с формой, необходимо будет добавить одноименное действие — GetPrimitive()
. Далее мы видим поля формы:
<input name='name' /><br /> <input type='number' name='age' /><br />
это два поля ввода, причем второе поле будет содержат только числа. Здесь нам важно обратить внимание на атрибут name
— по значению этого атрибута ASP.NET Core будет связывать значения в полях формы с параметрами в методе контроллера, который будет обрабатывать форму.
Передача примитивных типов данных
Теперь снова вернемся к контроллеру FormController
и создадим новое действие:
[HttpPost] public string GetPrimitive(string name, int age) { return $"{name} - {age}"; }
Здесь стоит обратить внимание на атрибут метода [HttpPost]
, который означает, что действие контроллера будет обрабатывать только POST-запросы — именно запросом POST и отправляются данные нашей формы в контроллер.
Посмотрим на результат. Загружаем форму и заносим данные:
Жмем кнопку «Отправить»
Как можно видеть, после отправки запроса мы перешли по путь Form/GetPrimitive
, то есть, по сути, наш контроллер выполнил одноименное действие и вывел имя и возраст человека.
Передача объектов
Для передачи объектов добавим в папку Models модель из предыдущей части:
namespace FirstMvcSite.Models { public class UserModel { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; } }
Теперь добавим в файл data.html следующую форму
<h3>Передача объектов</h3> <form method='post' action='Form/GetObject'> <label>ID:</label><br /> <input type='number' name='id' /><br /> <label>Имя:</label><br /> <input name='name' /><br /> <label>Email:</label><br /> <input name='email' /><br /> <input type='submit' value='Отправить' /> </form>
здесь стоит отметить, что атрибуты name
полей ввода полностью совпадают с именами свойств модели (без учёта регистра), а POST-запрос будет отправляться по пути Form/GetObject
. Определим новое действие в контроллере FormController
:
[HttpPost] public string GetObject(UserModel model) { return $"{model.Id} - {model.Name} - {model.Email}"; }
Проверим результат:
отправляем форму
Передача массивов
Добавляем в файл data.html следующую форму:
<h3>Передача массивов</h3> <form method='post' action='Form/GetArray'> <label>Первое число:</label><br /> <input type='number' name='num' /><br /> <label>Второе число:</label><br /> <input type='number' name='num' /><br /> <label>Третье число:</label><br /> <input type='number' name='num' /><br /> <input type='submit' value='Отправить' /> </form>
здесь каждое поле формы содержит в атрибуте name
одно и тоже значение. Теперь добавим новое действие в контроллер:
[HttpPost] public string GetArray(int[] num) { return $"Сумма элементов равна: {num.Sum()}"; }
В этом методе имя параметра полностью совпадает со значением атрибута name
в полях формы
Проверяем работу:
результат отправки формы
Передача массива объектов
Добавим в data.html новую форму
<h3>Передача массива объектов</h3> <form method='post' action='Form/GetObjectArray'> <b>Первый объект</b> <label>ID:</label><br /> <input type='number' name='user[0].id' /><br /> <label>Имя:</label><br /> <input name='user[0].name' /><br /> <label>Email:</label><br /> <input name='user[0].email' /><br /> <hr> <b>Второй объект</b> <label>ID:</label><br /> <input type='number' name='user[1].id' /><br /> <label>Имя:</label><br /> <input name='user[1].name' /><br /> <label>Email:</label><br /> <input name='user[1].email' /><br /> <hr> <b>Третий объект</b> <label>ID:</label><br /> <input type='number' name='user[2].id' /><br /> <label>Имя:</label><br /> <input name='user[2].name' /><br /> <label>Email:</label><br /> <input name='user[2].email' /><br /> <input type='submit' value='Отправить' /> </form>
Здесь в атрибуте name указывается имя массива, порядковый номер объекта в массиве и название свойства объекта, например, user[1].id
— ID второго объекта в массиве user
. Добавим новое действие в контроллер
[HttpPost] public string GetObjectArray(UserModel[] user) { return string.Join("\n", user.Select(s => $"{s.Id} - {s.Name} - {s.Email}")); }
Проверим результат работы:
результат обработки запроса контроллером
Передача словарей
Добавим в файл data.html следующую форму
<h3>Передача словарей</h3> <form method='post' action='Form/GetDictionary'> <b>Первый элемент</b> <hr> <label>Фрукт:</label><br /> <input name='dict[fruit]' /><br /> <b>Второй элемент</b> <hr> <label>Число:</label><br /> <input type='number' name='dict[number]' /><br /> <b>Третий элемент</b> <hr> <label>Текст:</label><br /> <input name='dict[text]' /><br /> <input type='submit' value='Отправить' /> </form>
здесь атрибут name содержит имя словаря и ключа в словаре.
Напишем следующее действие контроллера:
[HttpPost] public string GetDictionary(Dictionary<string, string> dict) { string result = ""; foreach (var item in dict) { result = $"{result} {item.Key} - {item.Value}; "; } return result; }
Проверяем работу приложения
результат
Использование свойства HttpContext для обработки форм
Также для получения данных из веб-форм можно использовать свойство HttpContext
. Например, добавим в data.html следующую форму:
<h3>Использование свойства HttpContext</h3> <form method='post' action='Form/GetData'> <label>Имя:</label><br /> <input name='name' /><br /> <label>Возраст:</label><br /> <input type='number' name='age' /><br /> <input type='submit' value='Отправить' /> </form>
и действие контроллера
[HttpPost] public string GetData() { return $"{HttpContext.Request.Form["name"]} - {HttpContext.Request.Form["age"]}"; }
здесь в метод GetData()
уже не требуется передавать никаких параметров, так как сведения о форме получаются напрямую из контекста запроса (свойство Form
объекта Request
). Для доступа к данным поля мы используем значение атрибута name
поля формы.
Итого
Обработка веб-форм в ASP.NET Core MVC, по большому счёту, ничем не отличается от получения данных контроллером из строки параметров запроса. Мы также можем передавать в формах примитивные типы, массивы, массивы объектов, словари и т.д. Важным является правильное задание значение атрибутов name
для полей формы. При этом, данные форм мы также можем получать и из свойства HttpContext
контроллера.