Создание текстового поля с автозаполнением
Ранее в этой главе мы узнали, как можно использовать Ajax и JSON для отправки запросов на сервер и получения данных. Кроме создания запросов Ajax вручную, можно также использовать клиентские библиотеки элементов управления и jQuery-плагины, которые позволяют абстрагироваться от стандартного кода для работы с запросами Ajax.
jQuery UI (http://jQueryui.com) является одним из таких наборов плагинов. Он построен на ядре jQuery и предоставляет несколько клиентских виджетов пользовательского интерфейса, в том числе «Аккордеон», автозаполнение, кнопки, календарь, диалоговое окно, индикатор выполнения, слайдер и вкладки.
В этом примере мы рассмотрим, как можно использовать плагин Autocomplete для создания списка городов с возможностью поиска, которая похожа на функциональность Google suggest, как на рисунке 7-10.
Рисунок 7-10: Google предлагает варианты, когда вы набираете текст

Создание CitiesController
Для начала мы создадим CitiesController
, который будет отображать страницу с текстовым полем, как показано в следующем листинге.
Листинг 7-22: CitiesController
public class CitiesController : Controller
{
private readonly CityRepository _repository;
public CitiesController()
{
_repository = new CityRepository();
}
public ActionResult Index()
{
return View();
}
}
Строка 6: Создает хранилище
CitiesController
создает экземпляр CityRepository
в своем конструкторе. Это хранилище содержит единственный метод, Find
, который принимает элемент поиска и находит все города, названия которых начинаются с указанного элемента. Внутренняя реализация CityRepository
не важна для данного примера, но если вы следите за образцами кода для этой главы, вы увидите, что она загружает данные о городах из CSV файла.
Сам класс City
представлен в следующем листинге.
Листинг 7-23: Создание класса City
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public string State { get; set; }
public string DisplayName
{
get { return Name + ", " + State; }
}
}
Объект City
представляет собой очень простой POCO (Plain Old CLR Object) - он просто определяет три перезаписываемых свойства (числовой идентификатор, название города и государства, в котором он находится) и одно свойство только для чтения, которое создает удобное для пользователя отображаемое имя.
Действие Index
демонстрирует представление, показанное в следующем листинге.
Листинг 7-24: Страница с автозаполнением
<script
src="@Url.Content("~/Scripts/jquery-1.7.1.js")"
type="text/javascript"></script>
<script
src="@Url.Content("~/Scripts/jquery-ui-1.8.16.js")"
type="text/javascript"></script>
<link
href="@Url.Content(
"~/content/themes/base/jquery-ui.css")"
rel="Stylesheet" type="text/css" />
<script type="text/javascript">
$(function () {
var autocompleteUrl = '@Url.Action("Find")';
$("input#city").autocomplete({
source: autocompleteUrl,
minLength: 2,
select: function (event, ui) {
alert("Selected " + ui.item.label);
}
});
});
</script>
<h2>Cities</h2>
<p>
Start typing a city to see
the autocomplete behavior in action.
</p>
<p>
<label for="city">City</label>
<input type="text" id="city" />
</p>
Строки 1-6: Ссылка на скрипты JQuery
Строки 7-10: Ссылка на стили JQuery UI
Строка 12: Обработчик готового дерева DOM
Строка 13: Создаем URL поиска
Строки 14-19: Добавляем сценарий автозаполения
Строка 30: Контейнер для результатов
Как и в предыдущих примерах, нам необходим jQuery. Если вы не изменяли макет, ссылки на эти сценарии уже включены.
Затем мы добавляем ссылку на стили jQuery UI, которые также включены в шаблон проекта по умолчанию. Опять же, если вы не изменяли макет, они у вас уже есть.
Далее следует блок скрипта, который запускается по окончании загрузки страницы. В первую очередь мы создаем в нем переменную autoCompleteUrl
, которая содержит URL-адрес действия Find
контроллера CitiesController
(который мы еще не создали). Это адрес, который будет запрашиваться каждый раз, когда пользователь вводит символ в поле поиска. Мы затем находим любое текстовое поле на странице с ID city и вызываем плагин Autocomplete на этом элементе. Ему сообщаем адрес, по которому он должен искать данные (в нашем случае autoCompleteUrl
), минимальное число символов, которое должно быть введено перед поиском (в нашем случае 2) и функцию обратного вызова, которая должна запускаться после того, как пользователь выбрал результат поиска. Для простоты, мы просто выводим на экран окно alert
с названием выбранного города. Наконец, мы определяем текстовое поле, которое позволит пользователю выполнять поиск.
Если мы сейчас запустим страницу, на ней будет отображаться текстовое поле. Однако так как мы еще не создали действие Find
, она будет выдавать ошибку, как показано на рисунке 7-11.
Рисунок 7-11: Текстовое поле с автозаполнением отправляет запрос Ajax, когда пользователь вводит поисковый запрос

Когда элемент поиска введен в поле, плагин Autocomplete отправляет запрос Ajax на сервер. В данном случае, он адресован к действию Find
и передает ему элемент поиска в виде строкового параметра запроса под названием term
. Плагин Autocomplete ожидает, что этот URL вернет массив объектов JSON со следующими свойствами: id
, label
(ярлык, который будет отображаться в результатах поиска) и value
(значение, которое будет вставлено в текстовое поле при нажатии).
На данный момент это вызывает ошибку 404, потому что у нас еще нет действия Find
. Давайте создадим его.
Листинг 7-25: Реализация действия Find
public ActionResult Find(string term)
{
City[] cities = _repository.FindCities(term);
var projection = from city in cities
select new
{
id = city.Id,
label = city.DisplayName,
value = city.DisplayName
};
return Json(projection.ToList(),
JsonRequestBehavior.AllowGet);
}
Строка 3: Поиск города
Строки 4-10: Создаем проекцию результатов
Строки 11-12: Преобразуем данные в JSON
Здесь мы сначала осуществляем поиск всех городов, имена которых начинаются с указанного символа. Затем мы используем LINQ-запрос "в памяти", чтобы сделать проекцию полученных объектов City
в коллекцию анонимных типов, которая соответствует структуре JSON и которую ожидает плагин Autocomplete (свойства id
, label
и value
). Наконец мы преобразовываем эти результаты в формат JSON путем вызова метода Json
. Как и в примере из листинга 7-13, мы должны явно разрешить передачу данных в формате JSON на запрос GET
с помощью поведения AllowGet
.
Наконец, когда вы повторно запустите страницу и введете поисковый запрос, вы увидите полученные с сервера результаты, как показано на рисунке 7-12.
Рисунок 7-12: Отображение результатов поиска

Вы также можете наблюдать получение данных JSON с сервера, отслеживая запросы Ajax с помощью Firebug, как показано на рисунке 7-13.
Рисунок 7-13: Получение данных JSON с сервера в ответ на поисковый запрос

Конечная страница позволяет нам выполнить поиск города, введя первые буквы его названия; сервер выполнит поиск и создаст соответствующий объект JSON. Плагин Autocomplete обработает результат и автоматически создаст раскрывающийся список, причем нам не нужно будет писать код для анализа результатов. Наконец, если мы выберем пункт в раскрывающемся списке, свойство value
объекта JSON будет вставлено в текстовое поле.