Последнее время все чаще и чаще слышны разговоры про Ajax. Появилось множество сайтов, использующих эту технологию, многие из них разработаны гигантами вроде Google или Microsoft. Ajax стал краеугольным механизмом для нового понятия Web 2.0. Так что же это такое — Ajax?
Ajax расшифровывается как Asynchronous JavaScript And XML, т. е. "асинхронный JavaScript и XML". Основное предназначение Ajax — осуществление запросов и получение данных для веб-страницы асинхронным способом, без перезагрузки самой страницы. Таким образом, пользователь не замечает запросы, посылаемые на сервер, а данные, передаваемые между сервером и клиентом, значительно уменьшаются в связи с тем, что пропадает надобность формировать и отправлять пользователю всю страницу целиком, по этой же причине снимается существенная нагрузка на сервер, которому нет нужды перестраивать страницу целиком или помещать ее в кэш.
Сама технология не нова, в той или иной мере она использовалась годами ранее, и только с широким распространением веб-сервисов появился специальный термин, который описывает не одну технологию, а подход к взаимодействию клиентского кода на стороне пользователя и бизнес-логике на сервере.
История успеха Ajax
Технология Ajax начала свою жизнь в середине 90-х годов. Когда вебтехнологии стали развиваться бурными темпами, появилась конкуренция браузеров и многие крупные компании старались внести свой вклад в создание будущего вида интернет-технологий. Так, компания Microsoft представила в 1996 году элемент iFrame, который позволял в одном окне браузера загружать данные из нескольких источников. Одним из применений iFrame стала незаметная для пользователя загрузка данных в скрытый фрейм с последующим использованием этих данных на основной странице. Можно сказать, что IFrame заложил некоторые основы Ajax, и даже сегодня данный подход широко используется на практике.
Чуть позднее компания Microsoft вновь внедрила инновационную технологию в свой браузер Internet Explorer, которая позволяла еще более просто асинхронно получать данные с сервера. Эта технология сегодня известна как объект XMLHttpRequest, который поддерживается всеми браузерами. Изначально XMLHttpRequest представлял собой ActiveX-компонент, который могли использовать разработчики, создающие свои продукты, нацеленные на работу в Internet Explorer. Этот компонент позволял при помощи JavaScript делать асинхронные запросы на сервер с получением данных в формате XML. Сама компания Microsoft использовала его в веб-версии почтового клиента Outlook.
Появление предка XMLHttpRequest можно считать рождением эры Web 2.0, хотя в то время ни такого термина, ни самого наступления новой эры никто не заметил. Потребовалось еще несколько лет, чтобы о технологии заговорили, и был даже придуман специальный термин. Значительное влияние на популяризацию и распространение технологии Ajax оказала компания Google, которая выпустила инновационные и сверхпопулярные в наше время проекты Gmail и Google Maps. Оба продукта Google не предлагали ничего нового: Gmail — это почтовый клиент, а Google Maps — сервис онлайн-карт, подобные которому уже существовали на рынке. Однако изменился сам подход и опыт использования приложений пользователем. Теперь вместо обязательных частых перезагрузок страницы при навигации по письмам или картографическому сервису пользователь получал интерфейс, который напоминал ему обычную настольную программу. Не было перезагрузок страницы с долгим ожиданием, вместо этого данные пользователя незаметно подгружались с сервера Google с использованием Ajax (рис. 7.1).
Пользователи очень быстро заслуженно оценили сервисы Google за их удобство, скорость работы и высокую отзывчивость. Кроме того, компания предложила беспрецендентный объем бесплатного почтового ящика в несколько гигабайт, но это уже другая история. Успех Gmail и Google Maps не прошел незамеченным, и технологией асинхронной передачи данных между браузером клиента и сервером стали интересоваться многие разработчики. Интерес к новому подходу при построении веб-сайтов все возрастал, все больше появлялось ресурсов, которые позволяли управлять собой без перезагрузок страницы, предлагая пользователю новый и интересный опыт общения с Интернетом.
В 2005 году Джейси Джеймс Гарретт, специалист по разработке пользовательских интерфейсов, придумывает специальный термин к технологии, которая уже заразила Интернет. Этим названием стал известный нам термин Ajax. В своей статье "Ajax: A New Approach to Web Applications" Гарретт описал как саму технологию, так и дал ей название. Ознакомиться с довольно объемной и подробной статьей можно и сегодня по адресу http://. 18 февраля 2005 года, день выхода статьи, можно считать днем рождения старой технологии под новым именем, которое изменило представление об Интернете.
В апреле 2006 года консорциум W3C утвердил первый черновик стандарта, который описывал объект XMLHttpRequest. Это стало заключительным аккордом в широком распространении технологии Ajax, теперь основополагающая технология была стандартизирована, и ничто не мешало ее дальнейшему распространению.
Современный Ajax
В наше время уже трудно найти новые веб-проекты, которые бы не использовали технологию Ajax. Да и многие другие старые и заслуженные ресурсы также получают обновление сервисов с включением Ajax в той или иной мере. Например, вслед за появлением Gmail другой популярный сервис Hotmail также обзавелся Ajax-интерфейсом, за ними последовали многие другие почтовые онлайн-сервисы.
Применение Ajax находится повсюду, например, крупнейший социальный сервис с IT-тематикой Habrahabr.ru использует Ajax для препросмотра написанной статьи или комментария, для изменения рейтинга записей и пользователей. Другие популярные социальные сервисы вроде Facebook или Spaces предпочитают использовать Ajax для простых действий наподобие подтверждения пользователем своих действий или работы с данными других пользователей сети.
Еще одним интересным применением Ajax, которое предлагает пользователю новый опыт при использовании интерфейсов веб-приложений, стало извлечение данных по требованию. Так, например, Google Reader, популярный сервис для чтения RSS-каналов, позволяет с помощью скроллирования получать все новые и новые данные RSS-ленты, хотя предзагружена изначально лишь малая их часть. Подобный вариант, только более наглядный для пользователя, использует поисковой сервис Bing, в котором реализован "бесконечный" поиск по изображениям. Новые результаты поиска в виде набора изображений будут подгружаться по мере того, как пользователь скроллирует страницу все ниже и ниже (рис. 7.2).
Помимо простого влияния Ajax на современное представление о пользовательских интерфейсах, технология Ajax оказывает огромное влияние на интернет-индустрию в целом. Ajax вдохнул вторую жизнь в веб-сайты, многие из которых стали дублировать функционал, который ранее казался привязанным к десктопу. Появились ресурсы, которые позволяют редактировать офисные документы или изображения. Движение Rich Internet Applications, которое, как ранее казалось, будет осуществляться посредством плагинов и сторонних технологий вроде Flash или Silverlight, теперь вполне осуществимо стандартными веб-технологиями на основе браузера, HTML и JavaScript. Конечно, RIA на базе веб-технологий пока отстает по производительности и возможностям от технологий Flash/Silverlight, но многие задачи, которые ранее решались с помощью Flash, теперь можно решить на базе усиленного с помощью Ajax HTML-интерфейса.
Широкое распространение Ajax не могло пройти мимо инструментов разработчиков, и почти все они обзавелись поддержкой Ajax, с помощью которой работа с Ajax-запросами значительно упрощается. Такие Framework, как ExtJS, jQuery, MooTools и другие популярные инструменты для разработки JavaScript-кода, конечно, имеют поддержку Ajax. Об одном из таких инструментов пойдет речь и в этой главе. jQuery — популярнейший JS Framework содержит несколько инструментов для удобной работы с Ajax и, что очень важно, включен в состав Visual Studio и проект MVC Framework по умолчанию.
Пример использования Ajax
Для того чтобы понять, что такое Ajax, достаточно рассмотреть один или несколько примеров его использования. Создадим реализацию классического примера, который использует механизм Ajax для получения текущего времени с сервера.
Первым делом мы должны создать экземпляр объекта XMLHttpRequest:
var xhr;
if (window.XMLHttpRequest)
{
xhr = new XMLHttpRequest();
}
else
if (window.ActiveXObject)
{
xhr = new ActiveXObj ect("Microsoft.XMLHTTP");
}
else
{
alert("Браузер не поддерживает XMLHttpRequest!");
}
Здесь в переменной xhr создается объект XMLHttpRequest. В зависимости от типа браузера доступ к этому объекту может быть разным. Старые версии Internet Explorer работают только через создание ActiveX-компонента. В Internet Explorer 7 и выше работа с XMLHttpRequest приведена к стандарту.
Для обработки результатов асинхронного запроса XMLHttpRequest используется свойство onreadystatechange, которое вызывается всякий раз, как объект XMLHttpRequest изменяет свое состояние. Для проверки текущего состояния используется другое свойство readyState, которое содержит значение текущего состояния XMLHttpRequest. Все возможные значения readyState перечислены далее:
□ readyState = 0 — запрос не инициализирован;
□ readyState = 1 — запрос был установлен;
□ readyState = 2 — запрос был отправлен;
□ readyState = 3 — запрос происходит в данное время;
□ readyState = 4 — запрос завершен, получен результат.
Другое свойство responseText отвечает за хранение ответа от сервера после запроса. Если совместить использование всех этих свойств вместе, то можно написать следующий часто используемый код обработки асинхронного запроса:
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
docum.ent.getElementById("timeText") .value = xhr.responseText;
}
}
Здесь свойству onreadystatechange присваивается функция для обработки изменения состояния объекта XMLHttpRequest, представленного переменной xhr. Функция проверяет свойство readyState на значение 4, которое говорит об успешном завершении запроса и присваивает элементу с идентификатором timeText текстовое значение результата запроса.
Для создания запроса к серверу используется две функции XMLHttpRequest: open и send. Функция open содержит три параметра:
□ текстовое значение с типом запроса: GET или POST;
□ текстовое значение со строкой запроса, указывающей на страницу, к которой необходимо выполнить запрос;
□ булево значение, определяющее, должен ли быть запрос асинхронным.
Функция send содержит один параметр, который должен определять данные, отправляемые вместе с запросом. Данные могут представлять собой как некую строку, так и XML-документ. В настоящее время чаще всего используется первый вариант, когда данные передаются в виде строки JSON-данных.
Для того чтобы отправить запрос на сервер, нужно вызвать следующий код:
xhr.open("GET","Home/GetTime",true);
xhr.send(null);
Запрос будет отправлен к ресурсу по относительному адресу Home/GetTime, когда сервер обработает запрос и пришлет ответ, в объекте xhr изменится состояние и будет вызвана наша реализация функции onreadystatechange.
Полный код примера, созданный на базе проекта MVC Framework по умолчанию, представлен в листинге 7.1.
Листинг 7.1
<%@ Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
runat="server">
Home Page
runat="server">
<%= Html.Encode(ViewData["Message"]) %>
To learn more about ASP.NET MVC visit
Время не получено
В этом фрагменте кода создается кнопка для запроса данных с сервера, к которой привязан JavaScript-код Ajax и текстовое поле для отображения результата.
Серверный код, необходимый для работы, примитивен и представляет собой следующую реализацию действия GetTime для контроллера HomeController. Обратите внимание на использование атрибута OutputCache для предотвращения кэширования результата, которое в нашем случае не нужно:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult GetTime()
{
return Json(DateTime.Now.ToString());
}
Запустив проект, мы можем запрашивать дату и время с сервера без перезагрузки страницы и с использованием технологии Ajax (рис. 7.3).
Мы рассмотрели принцип работы Ajax на базе XMLHttpRequest на простейшем примере. В действительности все несколько сложнее. Следует учитывать возможные ошибки, которые могут возникнуть при обработке запроса, необходимо обрабатывать истечение времени ожидания ответа от сервера. Для упрощения работы с Ajax существуют специальные библиотеки и Framework, про которые речь пойдет далее.
MVC Framework и Ajax
MVC Framework, как новый и современный инструмент, конечно, поддерживает Ajax и предлагает удобные и обширные средства по работе с ним. На самом деле MVC Framework содержит два отдельных Ajax-инструмента: стандартную библиотеку с классами-помощниками и библиотеку jQuery, одной из возможностей которой является упрощенная работа с Ajax.
Ajax-функционал в MVC Framework
В состав проекта MVC Framework по умолчанию входят два JavaScript-файла: MicrosoftAjax.js и MicrosoftMvcAjax.js, в которых для разработчиков предложены вспомогательные функции при работе с Ajax. Рассмотрим их по порядку:
□ MicrosoftAjax.js — основной файл, который содержит всю инфраструктуру ASP.NET для работы с Ajax. Эта библиотека может быть знакома тем, кто использовал Ajax.NET или AjaxControlToolkit в проектах на базе классического ASP.NET;
□ MicrosoftMvcAjax.js — файл, осуществляющий поддержку Ajax в MVC-проектах, код которых написан с помощью специальных вспомогательных методов. Эта библиотека использует MicrosoftAjax.js для своей работы.
Для упрощения работы с Ajax MVC Framework содержит кроме JavaScript-файлов еще и расширения в виде классов и методов .NET. Так, класс viewPage, по умолчанию базовый для всех страниц MVC-проектов, содержит свойство Ajax, которое является экземпляром класса AjaxHelper.AjaxHelper содержит перечисленные в табл. 7.1 вспомогательные методы для работы с Ajax в представлениях.
Чтобы использовать данные расширения в своих проектах, необходимо подключить оба JavaScript-файла, MicrosoftAjax.js и MicrosoftMvcAjax.js, на необходимую страницу либо для всех страниц сразу через файл master-страницы. Код для добавления ссылок на эти файлы в master-странице может быть следующим:
Далее мы рассмотрим более подробно эти вспомогательные методы и еще один вспомогательный класс AjaxOptions и свойство IsAjaxRequest, также имеющие отношение к Ajax.
AjaxOptions
Класс AjaxOptions представляет собой набор свойств, которые описывают разнообразные опции Ajax-запросов для вспомогательных методов MVC Framework. AjaxOptions содержит следующие свойства:
□ Confirm — задает текст, который будет выведен в запросе пользователю перед осуществлением запроса. Установка этого параметра приведет к тому, что перед запросом на сервер у пользователя будет возможность подтвердить отправку запроса или отменить ее (рис. 7.4);
Рис. 7.4. Запрос подтверждения при использовании параметра Confirm
□ HttpMethod — устанавливает тип HTTP-запроса (GET или POST), который будет использоваться при формировании асинхронного запроса. Может содержать одно из двух значений Get или Post, по умолчанию установлено в Post;
□ InsertionMode — свойство задает одно из значений одноименного перечисления InsertionMode: Replace, InsertBefore, InsertAfter. Значение по умолчанию Replace. Данное свойство устанавливает метод включения данных из ответа от сервера в элемент разметки: перезапись значения элемента, добавление до содержимого или после него. Данное свойство используется совместно со свойством UpdateTargetId, указывающим идентификатор элемента разметки, в которое будет записано значение результата ответа от сервера;
□ LoadingElementId — задает идентификатор элемента разметки, который должен быть отображен во время Ajax-запроса. Использование данного свойства приведет к тому, что указанный элемент будет показан во время запроса, а затем скрыт. Использование этого свойства имеет смысл для демонстрации пользователю анимации ожидания во время продолжительных запросов;
□ OnBegin — задает наименование JavaScript-функции, которая должна быть вызвана непосредственно перед отправкой асинхронного запроса на сервер;
□ Oncomplete — задает наименование JavaScript-функции, которая должна быть вызвана сразу после того, как запрос был завершен, и до того, как результат запроса был записан в элемент разметки. Не имеет значения, был ли завершен запрос удачно или нет, функция, указанная через Oncomplete, все равно будет вызвана. Данная функция будет вызвана до onFailure или onSuccess. Если требуется, чтобы результат не был записан в элемент разметки, то функция, указанная в Oncomplete, должна вернуть false;
□ OnFailure — задает наименование JavaScript-функции, которая должна быть вызвана в случае, когда асинхронный запрос завершился с ошибкой;
□ OnSuccess — задает наименование JavaScript-функции, которая должна быть вызвана в случае, когда асинхронный запрос завершился успешно;
□ updateTargetid — задает идентификатор элемента разметки, в который должен быть записан результат асинхронного запроса на сервер. Вместе с этим параметром может быть использован параметр InsertionMode, который указывает, каким именно способом должны быть записаны данные в элемент разметки;
□ url — устанавливает значение адреса сервера, куда следует отправить запрос. Свойство использовать не обязательно, когда класс AjaxOptions применяется в Ajax.BeginForm и Ajax.ActionLink, где действие и контроллер задают данные адреса. В случае если Url все же будет указан, он переопределит значения, определенные в этих методах.
Класс AjaxOptions и его свойства используются во вспомогательных методах Ajax.BeginForm и Ajax.ActionLink для тонкой настройки асинхронного запроса и его параметров, а также действий, осуществляемых в ответ на изменение состояния запроса. Например, в следующием фрагменте кода AjaxOptions используется для задания ряда параметров при вызове Ajax.ActionLink:
<%= Ajax.ActionLink("получить время", "GetTime", "Home",
new AjaxOptions() {
OnFailure="OnError",
Confirm="Bы уверены?",
UpdateTargetId = "timeText"
},
(object) null)
%>
Нажмите на ссылку для получения времени<^span>
Ajax.BeginForm
Вспомогательный метод Ajax.BeginForm, в зависимости от реализации, содержит набор из следующих параметров:
□ actionName — указывает наименование действия, которое следует вызвать в запросе, в случае, когда используется вариант метода без указания контроллера, вызывается действие контроллера текущего контекста;
□ controllerName — указывает наименование контроллера (сокращенное, без суффикса Controller), в котором следует искать и вызвать указанное в параметре actionName действие;
□ routeValues — указывает объект, содержащий параметры для механизма маршрутизации;
□ ajaxOptions — указывает экземпляр класса AjaxOptions с заданными свойствами, которые определяют параметры асинхронного запроса и могут определять ряд JavaScript-функций, реагирующих на изменение состояния запроса;
□ htmlAttributes — набор значений пользовательских атрибутов для тега form, которые должны быть помещены в разметку формы.
Ajax-расширения MVC Framework могут значительно облегчить работу по созданию Ajax-функционала как для форм, так и для простых запросов. Например, следующий код описывает создание простой Ajax-формы:
<% using(Aj ax.BeginForm("LoginForm",
new AjaxOptions{UpdateTargetId="loginStatus"})) {
%>
-
Введите логин и пароль, чтобы продолжить.
- Введите логин:
- <%= Html.TextBox("login")%>
- Введите пароль:
- <%= Html.TextBox("password")%>
<% } %>
Здесь с помощью вспомогательного метода Ajax.BeginForm создается стандартная форма авторизации с двумя текстовыми полями для ввода логина и пароля и кнопкой отправки данных. Обратите внимание на параметры Ajax.BeginForm: во-первых, указывается LoginForm — наименование действия, которое должно вызваться в ответ на отправку данных с формы, во-вторых, с помощью класса AjaxOptions задается специальный параметр UpdateTargetId, который указывает на элемент, ответственный за отображение результата запроса. То есть, если запрос вернет данные, они будут отображены, в нашем случае, с помощью элемента span с идентификатором loginStatus.
Как можно заметить, создание всего Ajax-функционала не потребовало у нас ни строчки JavaScript, не требуется от нас и понимание различий реализаций поддержки Ajax разными браузерами. Все это скрытно реализуют библиотеки MicrosoftAjax.js и MicrosoftMvcAjax.js, делая за разработчика всю рутинную работу по организации работы с асинхронными запросами. Если мы взглянем на исходный код, который сгенерирует подсистема Ajax в MVC Framework для нашего кода, то сможем убедиться, что генерируется достаточно много автоматического кода. Далее представлено определение формы, которое создано автоматически для нашего примера:
Ajax.ActionLink
Вспомогательный метод Ajax.ActionLink, в зависимости от реализации, содержит набор из нескольких следующих параметров:
□ linkText — текст, который будет рендериться в виде значения гиперссылки;
□ actionName — указывает наименование действия, которое следует вызвать в запросе, в случае, когда используется вариант метода без указания контроллера, вызывается действие контроллера текущего контекста;
□ controllerName — указывает наименование контроллера (сокращенное, без суффикса Controller), в котором следует искать и вызвать указанное в параметре actionName действие;
□ protocol — указывает используемый для формирования ссылки протокол http или https;
□ hostName — указывает значение хоста, которое будет использовано для формирования ссылки;
□ fragment — указывает значение якоря, которое будет использовано для формирования ссылки. Это значение используется браузером для навигации по странице и обычно представляет собой значение идентификатора какого-либо элемента разметки, к которому следует выполнить навигацию. Данное значение будет добавлено к ссылке в следующем виде: ;
□ routeValues — указывает объект, содержащий параметры для механизма маршрутизации;
□ ajaxOptions — указывает экземпляр класса AjaxOptions с заданными свойствами, которые определяют параметры асинхронного запроса и могут определять ряд JavaScript-функций, реагирующих на изменение состояния запроса;
□ htmlAttributes — набор значений пользовательских атрибутов для тега a, которые должны быть помещены в разметку формы.
Применение ActionLink еще проще, рассмотрим его использование на примере получения даты и времени для отображения на странице:
<%= Ajax.ActioriLink(''Пaлучить время", "GetTime", "Home",
new AjaxOptions() { UpdateTargetId = "timeText" },
(object) null) %>
Нажмите на ссылку для получения времени
Здесь с помощью вспомогательного метода Ajax.ActionLink создается ссылка, которая с помощью Ajax.NET скрытно связывается с асинхронным запросом на сервер. Кроме текста ссылки, наименования действия и контроллера, в функцию передается набор параметров AjaxOptions, в котором, в нашем случае, параметр UpdateTargetId устанавливается равным идентификатору элемента, где будет отображен результат запроса. В последний параметр, который определяет значение атрибутов HTML-элемента, передается значение (object) null, чтобы указать, что никаких дополнительных HTML-атрибутов рендерить не нужно.
Как и в случае использования Ajax.BeginForm, при рендеринге Ajax.ActionLink незаметно для разработчика создается вспомогательный код, который реализует весь Ajax-функционал, избавляя разработчика от написания рутинного кода:
После того как пользователь нажмет на ссылку, сформируется асинхронный запрос на сервер, и полученный результат будет выведен в элемент span с идентификатором timeText.
IsAjaxRequest
Метод IsAjaxRequest является методом расширения для класса HttpRequestBase. Данный метод возвращает булево значение, которое сообщает, является ли текущй запрос Ajax-запросом или нет. IsAjaxRequest может быть полезен тогда, когда ваше действие меняет логику в зависимости от типа запроса. Например, в следующем примере представлена реализация действия, в котором в зависимости от типа запроса возвращается либо набор данных, либо данные с готовой HTML-разметкой:
public ActionResult GetTime()
{
if (Request.IsAjaxRequestO)
{
return Json(DateTime.Now.ToString());
} else
return View(DateTime.Now.ToString());
}
jQuery
С недавних пор jQuery стала частью пакета Visual Studio. В среде разработчиков, работающих с JavaScript, jQuery зарекомендовала себя очень хорошо, и разработчики пакета Visual Studio решили не изобретать свой вариант JavaScript-библиотеки для работы с селекторами и DOM-моделью документа, когда встал такой вопрос, а взять готовый мощный отлаженный и знакомый многим разработчикам инструмент.
Одна из самых главных возможностей, которую предлагает jQuery, — это написание JavaScript-кода для работы с объектной моделью документа, основанного на селекторах CSS3. Селекторы CSS3 — это возможность назначить CSS-стиль не просто отдельному элементу в документе по его классу или идентификатору, но выбрать целый ряд элементов согласно некому общему признаку. Например, следующий CSS-код устанавливает стиль всем вложенным элементам li относительно элементов с классом . list:
.list > li {
color: #FFFFFF;
}
CSS-селекторы содержат гибкие варианты и операторы для доступа к элементам DOM для самых различных сценариев. Поддержка CSS-селекторов библиотекой jQuery означает, что вы получаете возможность проще выбирать часть объектов модели документа, используя знакомый CSS-синтаксис и минимум кода.
Примечание
Описание CSS-селекторов выходит за рамки этой статьи. Достаточно сказать лишь, что это важнейший и мощный инструмент по работе с DOM-моделью документа, и jQuery позволяет работать с dom на базе набора последней, третьей версии CSS-селекторов.
*********************************
Библиотека jQuery представлена в Visual Studio двумя JS-файлами: jquery-1.3.1js и jquery-1.3.1.min.js (на момент написания книги). Эти файлы идентичны по функционалу и отличаются только тем, что второй вариант минимизирован, т. е. текст его максимально оптимизирован для уменьшения размера (убраны переносы, лишние пробелы и выполнены другие оптимизации). Обычно первый вариант библиотеки используют при разработке и отладке, поскольку, кроме читаемого кода, библиотека содержит массу полезных комментариев. Второй вариант, специально уменьшенный, используется уже на реальном применении.
Для упрощения работы с библиотекой Visual Studio содержит специальные файлы *- vsdocjs, которые необходимы для поддержки IntelliSense при работе с функциями и свойствами jQuery. Чтобы использовать эти файлы, вам необходимо иметь Visual Studio 2008 с первым сервис-паком и установленным обновлением VS90SP1-KB958502-x86. Если у вас установлено это обновление, то после подключения скрипта jQuery к странице через тег script, вы получите возможность работать с функциями и свойствами библиотеки jQuery с помощью IntelliSense (рис. 7.5).
jQuery содержит ряд фукций по работе с Ajax, перечислим их и приведем основное назначение:
□ jQuery.ajax — выполняет Ajax-запрос на сервер;
□ load — выполняет Ajax-запрос на сервер и вставляет результат в DOM страницы;
□ jQuery.get — упрощенная версия jQuery.ajax, которая позволяет посылать GET-запросы на сервер с помощью Ajax;
□ jQuery .getJSON — версия jQuery.get, которая загружает с сервера данные в формате JSON с помощью Ajax-запросов;
□ jQuery.getscript — загружает с помощью Ajax текст JavaScript-кода и исполняет его;
□ jQuery.post — загружает данные с сервера с использованием Ajax и POST-запроса.
Кроме данных функций, jQuery содержит набор из нескольких событий и вспомогательных функций, которые будут рассмотрены в следующей части главы, посвященной jQuery.
Рассмотрим использование jQuery на примере решения знакомой нам задачи с выводом текущей даты и времени на сервере с помощью Ajax-запроса. Для этого перепишем функцию GetTime из предыдущей JavaScript-реализации на jQuery:
Сравните JavaScript-реализацию без вспомогательных библиотек с 20 строками и jQuery с шестью. Разница очевидна: использование jQuery не требует ни организации поддержки всех браузеров, ни обработки получения результата и состояния запроса. Все это низкоуровневое взаимодействие jQuery берет на себя. В приведенном примере использована функция jQuery $.get ($ — это синоним объекта jQuery). В функцию get передаются следующие параметры:
□ строка с адресом запроса;
□ null — как значение данных, передаваемых на сервер;
□ функция обратного вызова, которая будет вызвана в случае завершения запроса;
□ строковый параметр со значением "text", определяющий тип данных ожидаемого результата запроса (в данном случае — обычный текст).
Очевидно, что использование jQuery способно существенно сократить время, требующееся на создание клиентского кода, в том числе для реализации Ajax-функционала.
MVC Framework содержит все необходимое для поддержки разработчиков в их стремлении делать современные веб-проекты с использованием технологий Ajax. Включенная во Framework библиотека jQuery позволяет работать с клиентским кодом и JavaScript и гораздо проще организовывать Ajax-запросы. Встроенные средства MVC Framework и AJAX.NET позволяют вывести работу с Ajax на новый уровень абстракции, который позволяет меньше заботиться о написании JavaScript и дает возможность разработчику сосредоточиться на решении задачи вместо того, чтобы организовывать низкоуровневые взаимодействия между разметкой и асинхронными запросами к серверу.
Библиотека jQuery
jQuery — это сторонняя для Visual Studio JavaScript-библиотека, которую разработал Джон Ресиг, евангелист организации Mozilla Foundation, которая выпускает популярный браузер Firefox. Библиотека jQuery была выпущена в начале 2006 года и очень быстро завоевала популярность среди разработчиков в связи со своей простотой и в то же время чрезвычайно сильными возможностями. Ее основное назначение — это упрощенная работа с DOM-элементами документа. Библиотека так построена, что в JavaScript стало возможным использовать для выборки и работы с элементами HTML-страницы селекторы, соответствующие CSS3-селекторам. Это позволяет значительно упростить работу с HTML, создание анимации и динамического изменения разметки.
Большей частью своей популярности jQuery обязана расширяемости. В связи с тем, что это библиотека поддерживает плагины, написание которых не представляет собой труда, за короткое время jQuery обзавелась огромным количеством дополнительных расширений, которые могут быть применены в самых разнообразных случаях. На данный момент насчитываются сотни плагинов для jQuery, и едва ли не ежедневно появляются новые. В связи с тем, что написание такого плагина — элементарное в jQuery дело, создать его может любой желающий, расширив функционал библиотеки под собственные нужды.
Кроме работы с DOM, библиотека jQuery имеет встроенные средства для упрощения работы с Ajax. jQuery берет на себя всю работу по унификации доступа к функционалу Ajax в разнообразных браузерах и предлагает разработчику несколько своих полезных функций. В отличие от вспомогательных Ajax-методов MVC Framework, работа с Ajax в jQuery не может обходиться без написания JavaScript-кода.
jQuery API
В этой главе мы уже рассмотрели некоторые функции jQuery и пример использования, который продемонстрировал, насколько упрощает жизнь разработчиков библиотека jQuery, благодаря которой отпадает потребность писать сопутствующий код, не относящийся непосредственно к решению задачи.
Здесь мы рассмотрим все функции и события Ajax, имеющиеся в библиотеке и составляющие API jQuery по работе с асинхронными запросами. В табл. 7.2 приведен список функций Ajax-подсистемы в jQuery.
Функции для работы с Ajax
jQuery.ajax
Функция предназначена для организации Ajax-запросов и представляет собой самый активный элемент jQuery API, но в то же время самый низкоуровневый. jQuery.ajax принимает один-единственный параметр — структуру данных, которая описывает все, что необходимо для организации асинхронного запроса. Структура данных может содержать следующие поля:
□ async — булево значение, определяющее, будет ли запрос асинхронным. По умолчанию async=true;
□ beforeSend — определяет функцию, которая будет вызвана перед отправкой асинхронного запроса. Этой функции передается единственный параметр текущий объект XMLHttpRequest;
□ cache — позволяет управлять кэшированием страниц, по умолчанию установлено cache=true;
□ complete — определяет функцию, которая вызывается в момент завершения запроса, в том числе в случае неудачного запроса. В функцию передается два параметра: текущий объект XMLHttpRequest и строка, которая указывает статус завершения запроса;
□ contentType — определяет строковое значение типа данных запроса (HTTP-заголовок content-type). По умолчанию значение устанавливается в application/x-www-form-urlencoded;
□ data — данные, представленные объектом или строкой, которые должны быть отправлены на сервер вместе с запросом;
□ dataFilter — определяет функцию, которая вызывается для полученных в результате запроса данных. Подразумевается, что данная функция проведет проверку данных и приведет их в безопасный для использования на стороне клиента вид. Функция принимает два параметра: собственно принятые с сервера данные и строковое значение типа данных;
□ dataType — строка, определяющая тип данных, который ожидается в результате запроса. В зависимости от некоторых условий по умолчанию значение этого параметра устанавливается в "xml" или "html";
□ error — определяет функцию, которая будет вызвана в случае возникновения какой-либо ошибки при выполнении асинхронного запроса. Функция принимает три параметра: текущий объект XMLHttpRequest, строку с описанием типа ошибки и опциональный объект с описанием исключения, если оно было вызвано;
□ global — булево значение, которое определяет, должно ли выполнение этого запроса быть глобальным, что приводит к реагированию на него функций, или вызов не должен вызывать глобальные события. По умолчанию global=true;
□ ifModified — булево значение, которое указывает, что запрос должен считаться только тогда, когда возвращенные данные отличаются с момента прошлого запроса. По умолчанию ifModified=false;
□ password — строка, содержащая пароль, который будет использован в случае, когда производится запрос с обязательной аутентификацией;
□ processData — булево значение, которое определяет, необходимо ли производить обработку отправляемых данных из объектного представления в строковое. По умолчанию установлено processData=true;
□ success — определяет функцию, которая будет вызвана в случае, если запрос успешно завершится. Функция принимает два параметра: объект, содержащий полученные от сервера данные, и строковое значение, указывающее статус результата запроса;
□ timeout — числовое значение, которое определяет время ожидания ответа от сервера, по истечении которого запрос будет считаться завершившимся с ошибкой;
□ type — строка, определяющая типа запроса (GET или POST), по умолчанию type="GET";
□ url — строка, определяющая адрес, к которому отправляется запрос. По умолчанию подразумевается текущая страница;
□ username — строка, определяющая имя пользователя, которое будет использовано в случае, когда производится запрос с обязательной аутентификацией;
□ xhr — определяет функцию, которая должна создавать объект XMLHttpRequest. По умолчанию функция создает такой объект через ActiveXObject, если это возможно, если нет, то используется объект XMLHttpRequest. Вы можете переопределить эту функцию для собственной реализации создания объекта XMLHttpRequest.
Как можно заметить, функция jQuery.ajax обладает очень большим количеством настроек. Однако, в связи с тем, что практически все они имеют значения по умолчанию, использование jQuery.ajax не представляет собой особой сложности. Так, далее представлен вариант запроса значения даты и времени с сервера с помощью jQuery.ajax:
При всем перечисленном количестве возможных параметров для функции jQuery.ajax использование ее не вызывает труда. Достаточно указать всего лишь три параметра: адрес, обработчик результата и ожидаемый тип результата. Этого достаточно в нашем случае для простейшего асинхронного запроса.
load
Данная функция применяется для уже готового результата селектора jQuery и предназначена для того, чтобы запросить с сервера HTML-код и внедрить его в выбранные ранее объекты. Функция содержит три параметра:
□ url — строка адреса для запроса на сервер. Данная строка может содержать любой допустимый селектор для фильтрации результатов запроса. Например, строка "Home/GetTime span.timeData" отправит запрос по адресу Home/GetTime, но результат запроса будет отфильтрован — из него будет выбран элемент (или элементы) span с CSS-классом timeData;
□ data (необязательно) — параметры запроса, которые следует отправить на сервер. Параметры могут быть представлены в двух видах. В первом случае, когда параметр представлен в виде строки, формируется GET-запрос. Во втором случае, когда параметры представлены в виде объектов и пар "ключ/значение", формируется POST-запрос;
□ callback (необязательно) — определяет функцию, которая будет вызвана после завершения запроса, удачного либо нет. Функция содержит три параметра: текст ответа, тип данных ответа и объект XMLHttpRequest.
Следующий пример загрузит значение времени в элемент с индентификатором timeText:
Как можно убедиться, асинхронный запрос и изменение значения элемента HTML-разметки уместилось всего в одной строке. Это крайне удобно в ряде случаев.
jQuery.get и jQuery.post
Данные функции являются упрощенными и более высокоуровневыми вариантами функции jQuery.ajax. Каждая из функций принимает четыре параметра:
□ url — строка адреса для запроса на сервер;
□ data (необязательно) — данные для отправления на сервер;
□ callback (необязательно) — определяет функцию, которая вызывается после завершения выполнения асинхронной операции;
□ type (необязательно) — строка, определяющая тип ожидаемых данных с сервера. Может принимать одно из следующих значений: "xml", "html", "script","json", "jsonp" или "text".
Применение этих функций вместо более комплексной jQuery.ajax оправдано в большинстве случаев. Различие между jQuery.get и jQuery.post только одно: первая выполняет GET-запрос, вторая — POST.
jQuery. getJSON
Функция jQuery.getJSON предназначена для упрощения работы с данными в формате JSON и получения их через Ajax. jQuery.getJSON поддерживает также работу с JSONP. Функция содержит три знакомых нам параметра:
□ url — строка адреса для запроса на сервер. Для сайтов, которые поддерживают JSONP, в этом параметре можно указать параметр callback=?, чтобы иметь возможность обратиться с Ajax-запросом к домену, отличному от текущего домена сервера;
□ data (необязательно) — параметры, которые необходимо отправить на сервер;
□ callback (необязательно) — определяет функцию, которая должна быть вызвана после завершения запроса.
Использование jQuery.getJSON оправдано в случаях, когда реализуется взаимодействие с сервером, в котором достоверно известно, что обмен данными будет производиться только на базе формата JSON.
jQuery.getScript
Функция jQuery.getScript предназначена для асинхронных запросов, результатами которых являются JavaScript-фрагменты кода. После получения такого фрагмента jQuery.getScript выполняет полученный код. Функция содержит всего два параметра:
□ url — строка адреса для запроса на сервер;
□ callback (необязательно) — определяет функцию, которая должна быть вызвана после завершения запроса, загрузки и выполнения JavaScript-фрагмента.
Использование jQuery.getScript не является самым распространенным вариантом асинхронных запросов. Однако эта функция может быть полезна в тех случаях, когда требуется динамически подгружать JavaScript-функционал.
jQuery. ajaxSetup
Функция jQuery.ajaxSetup не является функцией, которая взаимодействует с сервером или занимается посылкой данных. Вместо этого jQuery.ajaxSetup предназначена для инициализации параметров, используемых по умолчанию при вызовах jQuery.ajax. Функция принимает только один параметр: options — структура данных, которая описывает все, что необходимо для организации асинхронного запроса. Возможные параметры структуры и их значения описаны вместе с описанием функции jQuery.ajax.
Например, чтобы изменить поведение по умолчанию для jQuery.ajax, чтобы вместо GET-запросов по умолчанию производились POST-запросы, необходимо вызвать следующий код:
$.ajaxSetup({ type: "POST" });
После этого все вызовы jQuery.ajax по умолчанию будут создавать POST-запросы. jQuery.ajaxSetup крайне полезна для инициализации сценария клиентской страницы, когда вместо того, чтобы передавать однотипные параметры с каждым вызовом jQuery.ajax, вы определяете их как значения по умолчанию.
События Ajax в jQuery
Помимо функций, работающих с Ajax, в библиотеке jQuery существует ряд функций, добавляющих обработчиков к событиям, которые также относятся к сфере Ajax и вызываются в тот или иной момент работы Ajax-запросов:
□ ajaxComplete — событие, возникающее в момент завершения Ajax-запроса. Результат завершения не влияет на возникновение события. ajaxComplete будет вызвано в любом случае: был ли запрос успешен, произошла ли ошибка, исключительная ситуация или время ожидания ответа от сервера истекло;
□ ajaxError — событие, возникающее в момент завершения Ajax-запроса с ошибкой. Событие ajaxError позволяет обработать исключительную ситуацию, возникшую при выполнении запроса на сервере, или другие ситуации, когда запрос не был успешно выполнен;
□ ajaxSend — событие, возникающее непосредственно перед отправкой запроса на сервер. Событие ajaxSend часто используется для изменения состояния пользовательского интерфейса, например, для запрещения элементов, с помощью которых может быть отправлен повторный запрос. Кроме того, разработчик может использовать событие ajaxSend для отображения сообщения для пользователя о том, что запрос был отправлен на сервер;
□ ajaxstart и ajaxstop — однотипные события, которые возникают в момент старта и остановки Ajax-запросов соответственно. Могут быть использованы точно так же, как ajaxsend или ajaxComplete, однако отличаются от них отсутствием параметров с дополнительными данными;
□ ajaxSuccess — событие, возникающее в момент успешного завершения Ajax-запроса. Если Ajax-запрос был выполнен успешно и были получены данные от сервера, то вызывается событие ajaxSuccess, обработав которое разработчик может отреагировать на успешный асинхронный запрос.
Все эти события могут быть обработаны пользовательскими функциями, в которые передается от одного до четырех параметров. Не принимают параметры только функции, обрабатывающие события ajaxstart и ajaxstop. Следующие параметры используются во всех остальных функциях:
□ event — объект, содержащий информацию о событии;
□ XMLHttpRequest — объект, содержащий информацию о запросе;
□ ajaxOptions — параметры, которые были использованы для запроса.
Событие ajaxError, кроме перечисленных трех, содержит четвертый параметр:
□ thrownError — объект, который содержит информацию о произошедшей ошибке.
Использовать данные события достаточно просто. Рассмотрим пример, который выводит пользователю сообщение о старте Ajax-запроса, скрывает кнопку, для предотвращения повторного запроса, и возвращает ее после того, как запрос выполнился. Для этого модифицируем код функции GetTime и разметку так, как представлено в следующем фрагменте:
Нажмите кнопку для 3anpoca
type="button"
onclick="javascript:GetTime()"
value="Получить время" />
Время не получено
Здесь представлена разметка для элемента requestStatus с отображением статуса Ajax-запроса, кнопки ajaxSend и элемента timeText для отображения результата запроса. В JavaScript-коде определены две функции для обработки ajaxStart и ajaxStop, которые отображают статус текущего состояния запроса и скрывают или показывают кнопку в зависимости от состояния. Для более явной демонстрации действия событий jQuery добавим в функцию GetTime контроллера HomeController задержку выполнения, чтобы увидеть, как изменяется сообщение о статусе запроса:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult GetTime()
{
Thread.Sleep(1000);
return Json(DateTime.Now.ToString());
}
Теперь, если пользователь нажмет кнопку Получить время, состояние запроса будет выведено в специальном поле (рис. 7.6). После получения результата поле состояния соответственно изменится (рис. 7.7).
Мы рассмотрели jQuery API, которое позволяет значительно упростить работу с Ajax-запросами как в целом, так и для частых практических ситуаций. Как мы убедились, некоторые варианты использования Ajax в jQuery могут состоять всего из одной строки текста. В следующей части главы мы рассмотрим применение jQuery более подробно.
Применение Ajax и jQuery в MVC Framework
Рассмотрим применение инструментов Ajax в MVC Framework на конкретных примерах. Для этого реализуем несколько простых сценариев в проекте MVC Framework по умолчанию. Чтобы охватить как можно больше, реализация будет выполнена в двух вариантах: с помощью ASP.NET Ajax и с помощью jQuery.
Пример 1. Проверка логина при регистрации
Первый пример, который мы рассмотрим, является решением частой задачи с помощью Ajax. В этом примере на форме регистрации добавляется функциональность по проверке введенного нового имени пользователя на наличие в базе данных. Задача проста: проверить, не является ли имя, которое себе выбрал пользователь, уже существующим на сайте.
Первоначально создадим действие Checkusername в контроллере Accountcontroller для реализации проверки на наличие имени пользователя на сайте. Далее представлен код метода checkusername, который принимает один строковый параметр username:
public ActionResult CheckUsername(string username)
{
string result;
if (String.IsNullOrEmpty(username))
{
result = "не указано имя пользователя";
}
else
{
var users = Membership.FindUsersByName(username);
result = users.Count > 0 ?
"такой пользователь уже существует" :
"ваше имя пользователя не занято";
}
return Json(result);
}
Данный метод принимает параметр с именем пользователя для проверки существования регистрации пользователя с таким именем. Метод CheckUsername возвращает строковое представление результата проверки.
Для вызова этого метода необходимо создать соответствующую разметку.
Реализация на ASP.NET Ajax
Добавим в Register.aspx ссылку для проверки введенного логина на наличие плюс поле для вывода результата проверки:
<%= Html.TextBox("username") %>
<%= Html.ValidationMessage("username") %>
<%= Ajax.ActionLink("Пpoверить доступность логина",
"CheckUsername",
new AjaxOptions {OnBegin ="CheckUsername_OnBegin"
, UpdateTargetld =
"check_username"}
)
%>
Здесь с помощью вспомогательного метода Ajax.ActionLink создается гиперссылка для вызова действия CheckUsername. C помощью создания структуры типа AjaxOptions мы задаем несколько параметров. Во-первых, мы задаем функцию CheckUsername_OnBegin, которая должна быть вызвана перед запросом, а во-вторых, указываем тег с идентификатором check_username, который должен быть использован для рендеринга результата.
К сожалению, базовый функционал ASP.NET Ajax пока не поддерживает возможность задавать динамические параметры для запросов, формируемых через Ajax.ActionLink. Поэтому, чтобы передать с запросом введенные пользователем данные, нам нужно обработать начало запроса и сформировать самостоятельно URL запроса с необходимой строкой параметров. Чтобы сделать это, мы задали функцию CheckUsername_OnBegin, код которой выглядит так:
Здесь производится получение URL запроса и формирование нового URL на базе введенных пользовательских данных. Последней строкой скрипта новый URL устанавливается для Ajax-запроса.
В итоге после компиляции на странице регистрации мы сможем увидеть рядом с полем ввода имени пользователя ссылку для проверки на допустимость такого логина (рис. 7.8). После нажатия кнопки пользователь получает результат проверки в виде строки сообщения (рис. 7.9).
Рис. 7.8. Форма регистрации с гиперссылкой на проверку доступности логина
Реализация на jQuery
Посмотрим, насколько реализация проверки на наличие логина на jQuery отличается от описанной ранее реализации на ASP.NET Ajax. Во-первых, определим гиперссылку для проверки логина пользователя:
<%= Html.TextBox("username") %>
<%= Html.ValidationMessage("username") %>
Проверить доступность логинаа>
Как можно заметить, определение гиперссылки является простым определением разметки, которая ничем не отличается от обычной. Основная работа ложится на код JavaScript, который представлен далее:
Здесь мы объявляем глобальный обработчик, который выполнится после загрузки документа $(document).ready (...). В этом обработчике мы задаем поведение для обработки нажатия пользователя на необходимую нам ссылку с идентификатором $("#checkUsername").bind("click", ...). В самом обработчике нажатия производятся следующие действия: получается значение введенного пользователем логина и с помощью функции load производится запрос на сервер для проверки пользовательских данных.
Нетрудно заметить, что в случае с jQuery нам пришлось произвести меньше действий. Во-первых, вместо определения серверного кода с определением Ajax.ActionLink мы сформировали с помощью HTML-разметки обыкновенную ссылку. Во-вторых, для передачи параметра с пользовательскими данными в случае jQuery нам не пришлось работать с внутренними объектами ASP.NET Ajax, вместо этого мы работали со ссылкой напрямую, сформировав ссылку для запроса обыкновенным сложением строк. И в-третьих, само количество кода для jQuery оказалось меньшим, чем потребовалось написать кода для ASP.NET Ajax.
Примечание
Следует заметить, что передача на сервер пользовательского ввода всегда сопряжена с опасностью. Злоумышленник может ввести в виде текста опасный код, например кусок SQL-кода или JavaScript-кода, который затем, в случае когда не проводится проверка пользовательского ввода, будет исполнен вашим сервером или браузером на компьютерах ваших пользователей. Чтобы избежать этого, необходимо всегда обрабатывать пользовательский ввод и учитывать его потенциальную опасность.
***********************************
Пример 2. Логин через Ajax
Второй пример будет представлять собой реализацию авторизации пользователя без перезагрузки страницы, с использованием только Ajax-запросов. Кроме того, сделаем так, чтобы возможность произвести вход в систему была доступна с любой страницы проекта.
Первоначально переопределим действие LogOn в контроллере Account так, чтобы поддержать возможность произведения входа в систему черезе Ajax-запросы (листинг 7.2).
Листинг 7.2. Переопределение действия LogOn
public ActionResult LogOn(string userName,
string password,
bool rememberMe,
string returnUrl)
{
if (Request.IsAjaxRequest())
{
var result = new AjaxResult();
if (!ValidateLogOn(userName, password))
{
result.IsSuccess = false;
result.ErrorString = "введен неверный логин или пароль";
return Json(result);
}
FormsAuth.SignIn(userName, rememberMe);
result.IsSuccess = true; return Json(result);
}
else
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
}
Обратите внимание на выделенный в листинге 7.2 фрагмент. В нем используется метод Request.IsAjaxRequest() для определения типа запроса. Если запрос был произведен с помощью Ajax, то выполнятся дальнейшая обработка и возврат результата в виде JSON-данных с булевым значением, описывающим, произведен ли вход в систему, и строкой описания ошибки, если она возникла. Когда запрос не является Ajax-запросом, выполняется предыдущая логика.
Реализация на ASP.NET Ajax
Сделаем так, чтобы вход в систему был возможен на любой странице проекта (рис. 7.10). Для этого добавим разметку, необходимую для отображения элементов управления входа в систему, в элемент управления LogOnUserControl.ascx:
<% if (Request.IsAuthenticated) { %>
Welcome <%= Html.Encode(Page.User.Identity.Name) %>!
[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]
<% } else { %>
<% using(Ajax.BeginForm("LogOn", "Account",
(object) null,
new AjaxOptions{OnSuccess = "OnLogon",
OnFailure = "OnError"})) {%>
Логин: <%= HtmL.TextBoxC'userNams'') %>
Пароль: <%= Html.Password ("password") %>
<%= HtmL.CheckBox("RememberMe") %> запомнить
<% } %>
Welcome !
[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]
<% } %>
#i_063.jpg
Здесь в выделенном фрагменте кода с помощью вспомогательного метода Ajax.BeginForm объявляется форма для ввода данных. Устанавливаются параметры формы: действие, контроллер, которые требуется вызвать. С помощью определения экземпляра AjaxOptions определяются параметры Ajax-запроса: при успешном запросе будет вызвана JavaScript-функция onLogon, при возникновении ошибки будет вызваана другая функция — onError. Определим логику этих JavaScript-функций, которые будут реагировать на результат Ajax-запросов (листинг 7.3).
Листинг 7.3. JavaScript-код для реагирования на события
Здесь определяются две JavaScript-функции: OnLogon и OnError. Первая функция предназначена для обработки результата успешного выполнения авторизации. Функция OnLogon принимает один параметр — result, который содержит результат выполнения запроса и дополнительные данные. Для получения JSON-данных, которые были получены от действия LogOn, в функции OnLogon используются сужебные функции ASP.NET Ajax:
□ get_response — возвращает объект с данными ответа от сервера;
□ get_responseData — позволяет получить строку данных, которые были возвращены действием контроллера;
□ Sys.Serialization.JavaScriptSerializer.deserialize — преобразует строку с JSON-данными в объект с соответствующими полями.
После обработки ответа и извлечения полученных данных, в зависимости от результата, формируется либо разметка, соответствующая приглашению пользователя, либо выводится строка с сообщением об ошибке.
Реализация на jQuery
Для реализации поставленной задачи с помощью jQuery необходимо определить следующую разметку элементов управления:
Здесь определена стандартная форма для отправки данных на сервер. Для обработки работы формы и формирования Ajax-запроса необходимо переопределить поведение формы с помощью JavaScript. Далее представлен фрагмент кода, определяющий логику работы формы:
Здесь определяется обработчик окончания загрузки документа, который после загрузки сайта в браузере у клиента выполнит необходимые привязки к разметке. Так, с помощью $('#loginForm').submit определяется функция, которая будет вызвана в момент, когда данные с формы будут передаваться на сервер. Обратите внимание на параметр event этой функции. После определения своей логики поведения при отправке данных с формы мы вызываем event.preventDefault(), который предотвращает поведение по умолчанию, т. е. позволяет нам отменить отправку данных с формы стандартным путем.
Для отправки данных мы используем функцию $.post, передав в нее предварительно сформированные данные, полученные с элементов управления. При вызове $.post мы определяем функцию OnResult, которая должна быть вызвана после завершения Ajax-запроса. Эта функция определяет обработку результата запроса и выводит либо сообщение об ошибке, либо приглашения для пользователя, в случае когда вход в систему был произведен удачно.
Полезные советы
В этой части главы мы рассмотрим несколько моментов, связанных с использванием технологии Ajax и библиотек jQuery и ASP.NET Ajax на практике.
Вопросы безопасности
Использование Ajax открывает новые возможности для разработчика и предлагает новый опыт для посетителя веб-ресурса. Но вместе с тем использование Ajax открывает новое поле действия для злоумышленников. Рассмотрим основные вопросы безопасности, которые следует иметь в виду при работе с запросами, в том числе и Ajax-запросами.
Обработка пользовательских данных
При работе с данными, полученными от пользователей, всегда необходимо соблюдать правила безопасности. Нужно относиться к любым таким данным как к потенциально опасным для отображения в разметке. Представим себе ситуацию, когда злоумышленник вместо того, чтобы ввести в поле своего логина какой-то текст, вводит туда опасный JavaScript-код. Тогда, если не принять никаких мер предосторожности, каждый из пользователей, который будет открывать страницу с выведенными данными злоумышленника на нашем сайте, потенциально будет уязвим. Предотвращение таких атак достигается путем декодирования опасного содержимого перед отображением на клиенте. В ASP.NET MVC существует метод расширения Html.Encode, который позволяет представить любой набор текстовых данных как безопасную последовательность символов и их HTML-представлений. Рассмотрим пример:
<%= Html.Encode("") %>
Очевидно, что если вывести строку, содержащую тег