ASP.NET MVC 4
Адам Фриман
Создание "ненавязчивой" Ajax формы
Теперь мы готовы начать применять ненавязчивого Ajax в нашем приложении, начиная с формы с ненавязчивым Ajax. В последующих разделах мы рассмотрим процесс замены обычных синхронных форм эквивалентным Ajax и объясним, как работает ненавязчивый Ajax.
Подготовка контроллера
Наша цель состоит в том, чтобы менялись только данные HTML элемента table
, когда пользователь нажимает на кнопку Submit
в нашем приложении. Это означает, что первое, что нам нужно сделать, это переделать методы действия в нашем контроллере People
так, чтобы мы могли получить только те данные, которые нам нужны. Вы можете увидеть изменения, которые мы внесли в контроллер People
, в листинге 21-8.
Листинг 21-8: Изменение методов действий в контроллере People
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using HelperMethods.Models;
namespace HelperMethods.Controllers
{
public class PeopleController : Controller
{
private Person[] personData = {
new Person {FirstName = "Adam", LastName = "Freeman", Role = Role.Admin},
new Person {FirstName = "Steven", LastName = "Sanderson", Role = Role.Admin},
new Person {FirstName = "Jacqui", LastName = "Griffyth", Role = Role.User},
new Person {FirstName = "John", LastName = "Smith", Role = Role.User},
new Person {FirstName = "Anne", LastName = "Jones", Role = Role.Guest}
};
public ActionResult Index()
{
return View();
}
public PartialViewResult GetPeopleData(string selectedRole = "All")
{
IEnumerable<Person> data = personData;
if (selectedRole != "All")
{
Role selected = (Role)Enum.Parse(typeof(Role), selectedRole);
data = personData.Where(p => p.Role == selected);
}
return PartialView(data);
}
public ActionResult GetPeople(string selectedRole = "All")
{
return View((object)selectedRole);
}
}
}
Мы добавили действие GetPeopleData
, оно выбирает объекты Person
, которые нам нужно отобразить, и передает их методу PartialView
для создания требуемых строк таблицы. Поскольку выборка данных обрабатывается методом действия GetPeopleData
, мы можем сильно упростить метод действия GetPeople
и полностью удалить версию HttpPost
. Цель этого метода состоит в передаче выбранной роли в виде string
в представление.
Мы создали новый файл частичного представления /Views/People/GetPeopleData.cshtml
для нового метода действия GetPeopleData
. Вы можете увидеть содержимое представления в листинге 21-9. Это представление отвечает за генерацию элементов tr
, которые будут заполнять таблицу, используя перечисление объектов Person
, которые передаются от метода действия.
Листинг 21-9: Создание представления GetPeopleData.cshtml
@using HelperMethods.Models
@model IEnumerable<Person>
@foreach (Person p in Model) {
<tr>
<td>@p.FirstName</td>
<td>@p.LastName</td>
<td>@p.Role</td>
</tr>
}
Мы также должны обновить представление /Views/People/GetPeople.cshtml
, которое вы можете увидеть в листинге 21-10.
Листинг 21-10: Обновление представления GetPeople.cshtml
@using HelperMethods.Models
@model string
@{
ViewBag.Title = "GetPeople";
}
<h2>Get People</h2>
<table>
<thead>
<tr>
<th>First</th>
<th>Last</th>
<th>Role</th>
</tr>
</thead>
<tbody>
@Html.Action("GetPeopleData", new {selectedRole = Model })
</tbody>
</table>
@using (Html.BeginForm()) {
<div>
@Html.DropDownList("selectedRole", new SelectList(
new [] {"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button type="submit">Submit</button>
</div>
}
Мы изменили тип модели представления на string
, который мы передаем вспомогательному методу Html.Action
для вызова дочернего действия GetPeopleData
. Это рендерит частичное представление и дает нам строки таблицы.
Создание Ajax формы
У нас после этих изменений еще есть синхронная форма в приложении, но мы выделили функциональность контроллера таким образом, мы можем запрашивать только строки таблицы через действие GetPeopleData
. Этот новый метод действия будет целью нашего Ajax запроса, и следующим шагом является обновление представления GetPeople.cshtml
, таким образом, чтобы работа с формой осуществлялась через Ajax, как показано в листинге 21-11.
Листинг 21-11: Создание ненавязчивой Ajax формы в представлении GetPeople.cshtml
@using HelperMethods.Models
@model string
@{
ViewBag.Title = "GetPeople";
AjaxOptions ajaxOpts = new AjaxOptions {
UpdateTargetId = "tableBody"
};
}
<h2>Get People</h2>
<table>
<thead>
<tr>
<th>First</th>
<th>Last</th>
<th>Role</th>
</tr>
</thead>
<tbody id="tableBody">
@Html.Action("GetPeopleData", new {selectedRole = Model })
</tbody>
</table>
@using (Ajax.BeginForm("GetPeopleData", ajaxOpts)) {
<div>
@Html.DropDownList("selectedRole", new SelectList(
new [] {"All"}.Concat(Enum.GetNames(typeof(Role)))))
<button type="submit">Submit</button>
</div>
}
Как вы можете видеть, изменения относительно мелкие, и нам не нужно вставлять блоки кода вокруг представления, чтобы все работало.
В центре поддержки MVC фреймворком Ajax форм находится вспомогательный метод Ajax.BeginForm
, который принимает в качестве аргумента объект AjaxOptions
. Нам нравится создавать объекты AjaxOptions
при запуске представления в блоке кода Razor, но вы можете создать их внутри, когда вызываете Ajax.BeginForm
.
Класс AjaxOptions
, находящийся в пространстве имен System.Web.Mvc.Ajax
, определяет свойства, которые позволяют нам конфигурировать то, как делается асинхронный запрос к серверу и что происходит с данными, которые мы получаем обратно. Эти свойства описаны в таблице 21 2.
Таблица 21-2: Свойства AjaxOptions
Свойство | Описание |
Confirm |
Задает сообщение, которое будет отображаться для пользователя в окне подтверждения, прежде чем будет сделан Ajax запрос. |
HttpMethod |
Задает HTTP метод, который будет использоваться для создания запроса. Это может быть либо Get , либо Post . |
InsertionMode |
Указывает способ, которым содержание, полученное с сервера, будет вставлено в HTML. Есть три варианта выбора: InsertAfter , InsertBefore и Replace (по умолчанию). |
LoadingElementId |
Указывает ID HTML элемента, который будет отображаться, пока выполняется Ajax запрос. |
LoadingElementDuration |
Задает продолжительность анимации, которая используется для выявления элемента, определенного LoadingElementId . |
UpdateTargetId |
Указывает ID HTML элемента, в который будет вставлен контент, полученный от сервера. |
Url |
Задает Url, который будет запрашиваться сервером. |
В листинге мы установили свойство UpdateTargetId
для tableBody
. Это id
, которое мы присвоили HTML элементу tbody
в представлении в листинге 21-11. Когда пользователь нажмет на кнопку Submit
, асинхронный запрос будет сделан к методу действия GetPeopleData
, а возвращенный HTML фрагмент будет использоваться для замены существующих элементов в tbody
.
Совет
Класс
AjaxOptions
также определяет свойства, которые позволяют нам указать функции обратного вызова для различных этапов жизненного цикла запроса, см. «Работа с функциями обратного вызова Ajax" далее в этой главе.
Ну вот и все: мы заменяем метод Html.BeginForm
Ajax.BeginForm
и убеждаемся, что у нас есть цель для нового содержания. Все остальное происходит автоматически, и мы получаем асинхронную форму.
Как работает ненавязчивый Ajax
Когда мы вызываем вспомогательный метод Ajax.BeginForm
, параметры, которые мы указали при помощи объекта AjaxOptions
, превращаются в атрибуты, применяемые к элементу form
. Наше представление в листинге 21-11 создает следующий элемент form
:
...
<form action="/People/GetPeopleData" data-ajax="true" data-ajax-mode="replace"
data-ajax-update="#tableBody" id="form0" method="post">
...
Когда HTML страница, полученная из представления GetPeople.cshtml
, загружается в браузер, JavaScript в библиотеке jquery.unobtrusive-ajax.js
сканирует HTML элементы и определяет Ajax форму, когда ищет элементы, у которых атрибуты data-ajax
имеют значение true
.
Остальные атрибуты, имена которых начинаются с data-ajax
, содержат значения, которые мы задали с помощью класса AjaxOptions
. Эти параметры конфигурации используются для настройки JQuery, который имеет встроенную поддержку для управления Ajax запросами.
Совет
Вы не обязательно должны использовать MVC фреймворк для поддержки ненавязчиво Ajax. Есть много альтернатив, в том числе использование JQuery напрямую. То есть, вы можете выбрать определенную технику и придерживаться ее. Мы не рекомендуем смешивать MVC поддержку ненавязчивого Ajax с другими методами и библиотеками в одном и том же представлении, поскольку это может вызвать некоторые проблемы, такие как дублирование или падение Ajax запросов.