microsoft asp.net 2.0 ajax

320
СЕРИЯ t** ,v 00Z>

Upload: sergey-kotsur

Post on 24-Mar-2016

276 views

Category:

Documents


12 download

DESCRIPTION

Microsoft ASP.NET 2.0 AJAX

TRANSCRIPT

Page 1: Microsoft ASP.NET 2.0 AJAX

С Е Р И Я

t * * , v

00Z>

Page 2: Microsoft ASP.NET 2.0 AJAX

Microsoft'

Introducing MicrosoftASP.NET 2.0 AJAX Extensions

Dino Esposito(Solid Quality Learning)

Page 3: Microsoft ASP.NET 2.0 AJAX

Дино Эспозито

3Microsoft

"D

шш ш тшгашшшггашй

ЙЖШ шм шш

.РУССКАЯ РЕДАКЦИЯ £^ПП7ШР°Москва ■ Санкт-Петербург ■ Нижний Новгород ■ ВоронежНовосибирск ■ Ростов-на-Дону ■ Екатеринбург ■ Самара

Киев ■ Харьков ■ Минск

2007

Page 4: Microsoft ASP.NET 2.0 AJAX

ББК 32.973-018.1

УДК 004.43

Эспозито Д.

Э85 Знакомство с технологией Microsoft ASP.NET 2.0 AJAX. — М.: «Русская

Редакция»; СПб.: Питер, 2007. — 320 с : ил.

ISBN 978-5-7502-0307-9 («Русская редакция»)ISBN 978-5-91180-435-0 («Питер»)

Книга представляет собой экспертное введение в расширение языка JavaScript (кодовоеназвание Atlas) для Microsoft ASP.NET 2.0, написанное специалистами, работающими в групперазработки. Эта книга является идеальным справочным пособием, поскольку содержит наиболеесвежие сведения о рассматриваемых в ней инструментах разработки, а также множество примеровна языках С# и JavaScript.

ББК 32.973-018.1

УДК 004.43

Подготовлено к печати по лицензионному договору сMicrosoft Corporation, Редмонд, Вашингтон, СШАMicrosoft, Microsoft Press, ActiveX, Internet Explorer, MSDN, MS-DOS, MSN, Outlook, PowerPoint, Verdana, virtual Earth, Visual Basic,Visual C#, Visual C++, Visual Studio, Windows, Windows Live, Windows Server иWindows Vista являются товарными знаками илиохраняемыми товарными знаками корпорации Microsoft в США и/или других странах. Все другие товарные знаки являютсясобственностью соответствующих фирм.Все названия компаний, организаций и продуктов, а также имена лиц, используемые в примерах, вымышлены и не имеютникакого отношения к реальным компаниям, организациям, продуктам и лицам.

ISBN 0-7356-2345-7 (англ.) © Оригинальное издание на английском языке, Dino Esposito, 2007ISBN 978-5-7502-0307-9 («Русская редакция») © Перевод на русский язык, Microsoft Corporation, 2007ISBN 978-5-91180-435-0 («Питер») © Оформление и подготовка к изданию ООО «Питер Пресс», ООО

«Издательство «Русская Редакция», 2007

Дино ЭспозитоЗнакомство с технологиейMicrosoft® ASP.NET 2.0 AJAX

Перевел с английского Е. Матвеев

Совместный проект издательства «Русская Редакция» и издательства «Питер»

« . Р У С С К А Я РЕДАКЦИЯ С^ПНТЕР

ООО «Питер Пресс», 198206, Санкт-Петербург, Петергофское шоссе, д. 73, лит. А29.Налоговая льгота — общероссийский классификатор продукции ОК 005-93, том 2; 95 3005 — литература учебная.

Подписано в печать 30.04.07. Формат 70x100/16. Усл. п. л. 25,8. Тираж 2000. Заказ 0000.Отпечатано по технологии CtP в ОАО «Печатный двор» им. А. М. Горького.

197110, Санкт-Петербург, Чкаловский пр., д. 15.

Page 5: Microsoft ASP.NET 2.0 AJAX

СодержаниеБлагодарности 9 От издательства 10

Для кого написана книга 12

Настройка конфигурации SQL Server 2005 Express Edition 13

Глава 1. Структурные элементы приложений в стиле AJAX 15

Получение вывода в страницах 17Достоинства и недостатки 18

Обновление страниц 20Модель DOM 20Роль широкофункционального браузера 21Расширенную функциональность — в массы! 21

Объект XmlHttpRequest в Mozilla 24XmlHttpRequest как интегрированный объект в Internet Explorer 7 25

Объектная модель HTTP 25Поведение и возможности 26

Использование объекта XmlHttpRequest 28Внеполосные вызовы из страниц ASP.NET 28

Существующие прикладные среды AJAX в .NET 32

Метод GetCallbackEventReference 35Интерфейс ICallbackEventHandler 36ASP.NET Script Callback: все вместе 37Основные факты 38

Page 6: Microsoft ASP.NET 2.0 AJAX

6 Содержание

Библиотека AJAX.NET: все вместе 41Основные факты 41

Прикладные среды на базе AJAX 42Web.UI (ComponentArt) 43

Глава 2. Структурные элементы Atlas 46

Развертывание приложений Atlas 49

JSON 51Atlas на других серверных платформах 52

Серверо-центрическая программная модель 54Клиенто-центрическая программная модель 57

Удаленный вызов методов 70

Глава 3. Частичное обновление страниц 83

Цели и побудительные мотивы 84

Включение частичного обновления страниц 86

Использование элемента UpdatePanel 91Управление обновлением страниц 96

Обновление панели по триггеру 96

Обратная связь во время обновления 103

Общие сведения об элементе UpdateProgress 104Отмена незавершенного обновления 105

Таймер 107

Page 7: Microsoft ASP.NET 2.0 AJAX

Содержание 7

Глава 4. Элементы Microsoft ASP.NET AJAX 110

Регистрация компонентов ACT в странице 113Содержимое ASP.NET AJAX Control Toolkit 114

Общие сведения об элементе Accordion 117Использование элемента Accordion 119

Элемет-Rating 121Общие сведения об элементе Rating 121Использование элемента Rating 123

Общие сведения об элементе ReorderList 124Использование элемента ReorderList 127

Серверные расширители Atlas 129

Общие сведения об аспектах поведения Atlas 130

Расширители временных окон 136Расширители пользовательского интерфейса 140

Глава 5. Библиотека Microsoft AJAX 162Расширения JavaScript 163

Объектно-ориентированные расширения в Atlas JavaScript 167

Компоненты Atlas 175Декларативные действия 177Другие компоненты и функциональные возможности 183

Элементы пользовательского интерфейса 188

Элементы проверки данных 193Аспекты поведения клиентской стороны 199

Глава 6. Обращение к серверным службам 214Встроенные прикладные службы 215

Связь с внешними веб-службами 253Вызов нелокальных веб-служб Atlas 253

Page 8: Microsoft ASP.NET 2.0 AJAX

8 Содержание

Настройка веб-служб во внешнем приложении Atlas 254

Глава 7. Привязка данных на стороне клиента 265

Клиентские компоненты источников данных 278Расширенные функции 286

Построение расширенных списковых представлений 286Отправка исходных данных 286Создание детализированных представлений 294

Live.com, Windows Vista и гаджеты 303Гаджеты и Atlas 307

Алфавитный указатель 318

Page 9: Microsoft ASP.NET 2.0 AJAX

Посвящается Сильвии«Изменяться и изменяться к лучшему — отнюдь не одно и то же».

Немецкая пословица

БлагодарностиНаписать вводную книгу по новой технологии — задача не из простых. Это осо-бенно справедливо в тех случаях, когда новая технология еще не была выпуще-на и по ней, естественно, не существует простой, готовой документации. Я осно-вательно проработал материалы проекта, используя все доступные средства — декомпиляторы, электронную почту, слайды с конференций, примеры кода и всюдокументацию, которая попадалась мне на глаза. Картину дополняли экспери-менты с бесчисленными примерами различной сложности. Короче говоря, я учил-ся методом проб и ошибок.

Первым, кто извлек пользу из этой книги, был я сам. Я использовал ее дляизучения ASP.NET Atlas. Могу сказать, что после знакомства с ней я неплохоразбираюсь в этой теме. Не знаю, какой вывод из этого можно сделать — то лия быстро учусь, то ли книга действительно получилась неплохой.

Я чрезвычайно благодарен Скотту Гатри (Scott Guthrie) за то, что он тратилна меня свое время, объясняя, что нас ждет впереди, и что группа разработчиковузнала в ходе работы над проектом — до и после Конференции профессио-нальных разработчиков в 2005 году, когда появилась первая информация о плат-форме Atlas. Саймон Кэлверт (Simon Calvert) стал моим «личным проводни-ком», а Стефан Шекоу (Stefan Schakow) предоставлял содержательные ответына мои вопросы (которые не всегда были умными). Я жадно читал блоги Бертра-на Лероя (Bertrand LeRoy) и Нихила Котари (Nikhil Kothari) — а также множе-ство других блогов — и нашел в них массу полезной информации.

Во время работы над книгой я также общался с парой фирм, работающих в об-ласти AJAX. Хочу особо поблагодарить Миляна Братишевича (Miljan Braticevic)из ComponentOne и Светозара Георгиева (Svetozar Georgiev) из Telerik. Atlas —замечательная штука, но эти парни со своими командами добились больших ус-пехов в создании приложений, которые работают по Сети почти так же, как про-граммы для настольных систем.

Чтобы написать эту книгу, я побывал на трех континентах и в шести странах:Италия, США, Франция, Испания, Австралия и Малайзия. Мои друзья ГрегЛинвуд (Greg Linwood) и Бретт Кларк (Brett Clarke) усомнились, удастся лимне написать целую главу за неделю, одновременно с обучением, экскурсиямипо Мельбурну и подготовке весьма специфической презентации Microsoft Power-Point для весьма специфического, весьма специфического дня рождения. Я спра-вился с задачей — и это было очень занятно.

Page 10: Microsoft ASP.NET 2.0 AJAX

1 0 Благодарности

Кого еще я должен поблагодарить? Ну конечно, моих любимых Линн Фин-нел (Lynn Finnel) и Кимберли Ким (Kimberly Kim) со всей группой редакти-рования, за их гибкость и снисходительность к перенесению сроков сдачи мате-риала вне всяких разумных пределов. Кенн Скрибнер (Kenn Scribner) осваивалAtlas вместе со мной и несколько раз наставил меня на путь истинный. (Конеч-но, иногда я делал то же самое, но между друзьями это дело обычное…)

Бен Райан (Ben Ryan) очень хотел увидеть эту книгу, и вот она вышла в свет.Спасибо, Бен!

Как обычно, я благодарен своей жене Сильвии и моим детям, Франческои Микеле, которые становятся все выше с каждой написанной мной книгой.

P.S.: Я пишу это предисловие в особый день — 11 сентября, пять лет спустя.

Выражаю сочувствие всем, кого затронула эта трагедия.Дино

От издательстваК тому моменту, когда книга уже была сверстана, компания Майкрософт не-ожиданно сменила кодовое имя технологии Atlas на ASP .NET 2.0 Ajax. Ввидутого, что объем исправлений по всей книге был бы неоправданно большим, ре-дакция приняла решение оставить в тексте кодовое имя Atlas. Мы извиняемсяперед читателями за возможные неудобства и просим обратить внимание на то,что везде, где в книге упоминается Atlas, под этим кодовым именем следует по-нимать ASP .NET 2.0 Ajax.

Ваши замечания, предложения и вопросы отправляйте по адресу электрон-ной почты [email protected] (издательство «Питер», компьютерная редакция).

Мы будем рады узнать ваше мнение!Подробную информацию о наших книгах вы найдете на веб-сайте издательст-

ва: http://www.piter.com.

Page 11: Microsoft ASP.NET 2.0 AJAX

ВведениеПрошли те времена, когда веб-приложение можно было сконструировать и реа-лизовать в виде простого набора связанных страниц. Появление так называемого«стиля AJAX» в корне изменило представления пользователей о веб-приложе-ниях, и как следствие, заставило разработчиков переходить на более новые и со-вершенные модели построения современных веб-приложений. Но что обычнопонимают под термином «стиль AJAX»?

Сокращение AJAX происходит от слов «Asynchronous JavaScript and XML»(«асинхронный код JavaScript и XML»). Этим общим термином обозначаютсявысокоинтерактивные приложения, быстро реагирующие на действия пользова-теля, выполняющие большую часть работы на стороне клиента и взаимодейст-вующие с сервером посредством внеполосных обращений. Внеполосным (out-of-band) обращением называется запрос к серверу, который приводит к оператив-ному обновлению страницы (вместо ее замены). В результате веб-приложенияна базе AJAX обычно в большей степени напоминают классические приложенияMicrosoft Windows, поддерживают перетаскивание и асинхронные операции, бы-стро реагируют на действия пользователя, не мигают при перерисовке и не раз-дражают пользователя.

Microsoft Atlas — важное расширение платформы Microsoft ASP.NET, обес-печивающее эффективную поддержку AJAX-функциональности в приложениях.Технология Atlas проектировалась как составная часть ASP.NET, и как след-ствие, она полностью интегрируется с существующей платформой разработкии моделью приложений. Полноценная поддержка Atlas будет включена в сле-дующую версию Microsoft Visual Studio (кодовое обозначение Orcas).

С архитектурной точки зрения, инфраструктура Atlas состоит из двух эле-ментов: библиотеки клиентских сценариев и набора серверных расширений.Библиотека клиентских сценариев полностью написана на JavaScript и поэтомуработает в любом современном браузере. Так как платформа Atlas являетсярасширением ASP.NET, она полностью интегрируется с серверными службамии управляющими элементами ASP.NET. В результате разработчики могут созда-вать веб-страницы с расширенной функциональностью на базе Atlas, используяпрактически такую же методику, которая использовалась при разработке клас-сических серверных страниц ASP.NET.

Большинство Atlas-разработчиков имеет опыт разработки ASP.NET, и какследствие, хорошо знакомы с серверной моделью разработки, основанной наэлементах управления. Серверо-центрическая модель программирования Atlas

Page 12: Microsoft ASP.NET 2.0 AJAX

12 Введение

является крупным шагом на пути эволюции программной модели ASP.NET.Серверные элементы Atlas чрезвычайно удобны — особенно если вы не чувст-вуете достаточной уверенности для того, чтобы создавать клиентские сценарииAtlas вручную.

В книге приводится общий обзор инфраструктуры Atlas, а многочисленныепримеры помогут в освоении различных приемов и инструментов программиро-вания.

Технология Atlas обещает стать настоящим прорывом для профессиональныхразработчиков ASP.NET. Благодаря ей кросс-браузерное программированиевоплощается в реальность, а веб-приложения обретают функциональность, ха-рактерную для настольных систем. А сегодня вы получаете Atlas в свое распо-ряжение, с лицензией Go-Live и полным набором возможностей — изучайте,пробуйте и экспериментируйте, невзирая на официальный бета-статус этой тех-нологии.

ПРИМЕЧАНИЕК моменту издания книги официальные имена продуктов семейства Atlas едва успелиопределиться. Новые имена делятся на три категории и могут заменять кодовые обозна-чения Atlas, использованные в тексте. Далее приводится список официальных имен.1. Клиентская библиотека JavaScript Atlas будет называться «библиотекой Microsoft

AJAX». Она будет работать в любом браузере и поддерживаться всеми внутреннимивеб-серверами.

2. Серверная функциональность Atlas, интегрированная сASP.NET, будет обозначать-ся термином «ASP.NET 2.0 AJAX Extensions». Как следствие, префикс тегов элемен-тов Atlas <atlas:> заменяется на <asp:>.

3. Инструментарий Atlas Control Toolkit на текущий момент представляет собой наборсвободно распространяемых элементов и компонентов с открытыми исходными ко-дами, которые помогают извлечь максимум пользы из расширений ASP.NET AJAXExtensions. В будущем проект будет называться ASP.NET AJAX Control Toolkit.

Для кого написана книгаКнигу можно порекомендовать практически всем разработчикам и профессио-налам в области ASP.NET. Как упоминалось ранее, платформа Atlas, котораядолжна стать следующим значительным этапом в эволюции ASP.NET, следуетглавной тенденции отрасли — модели AJAX. Кроме того, Atlas выходит за рамкимодели AJAX и расширяет инфраструктуру взаимодействия клиента с серве-ром, обеспечивая комплексное решение для веб-приложений. В том, что касает-ся веб-платформы Microsoft, Atlas объединяет расширенную функциональностьс универсальностью — старая мечта веб-профессионалов, которая воплотиласьв жизнь. Наконец-то.

Если вы принадлежите к числу профессионалов, занимающихся разработка-ми для веб-технологий Microsoft, Atlas откроет для вас благоприятную возмож-ность; не упускайте ее. Пусть эта книга станет отправной точкой в изучении но-вой технологии.

Page 13: Microsoft ASP.NET 2.0 AJAX

Настройка конфигурации SQL Server 2005 Express Edition 1 3

Как устроена книгаМатериал делится на три части: общие сведения о платформе, разработка на сто-роне сервера и разработка на стороне клиента. В первой части рассматриваютсяосновные принципы модели AJAX и их реализация в Atlas. Вторая часть посвя-щена элементам инфраструктуры Atlas, используемым для расширения возмож-ностей серверных элементов и преобразования существующих классических стра-ниц ASP.NET в полноценные страницы Atlas. Наконец, в третьей части книгиподробно разбирается внутреннее устройство Atlas: клиентская библиотека,клиентские элементы, интеграция веб-служб, привязка данных и гибридные(mash-up) приложения.

Вторая и третья части построены на независимом материале. Если вас интересу-ет лишь включение поддержки AJAX в классических страницах ASP.NET, запол-ненных элементами runat=server, вероятно, материал третьей части вам практи-чески не понадобится. Для начала хватит и содержания первых глав. Тем не менеев третьей части рассматриваются методы и инструменты, лежащие в основе мощиAtlas — клиентские элементы и фрагменты XML Script, которые могут использо-ваться для преодоления различий между браузерами и синтаксисом JavaScript.

Системные требованияДля построения и запуска примеров кода, приводимых в книге, потребуется сле-дующее аппаратное и программное обеспечение:I Microsoft Windows XP с обновлением Service Pack 2, Microsoft Windows

Server 2003 c обновлением Service Pack 1 или Microsoft Windows 2000 с об-новлением Service Pack 4.

I Microsoft Visual Studio 2005 Standard Edition или Microsoft Visual Studio 2005Professional Edition.

I Microsoft SQL Server 2005 Express (поставляется с Visual Studio 2005) илиMicrosoft SQL Server 2005.

I 600-МГц Pentium или совместимый процессор (рекомендуется 1 ГГц Pentium).I 192 Мбайт оперативной памяти (рекомендуется 256 Мбайт и более).I Монитор (разрешение 800x600 и выше) с поддержкой не менее 256 цветов

(рекомендуется 1024x768 с 16-разрядным цветом High Color).I Мышь Microsoft или совместимое указывающее устройство.

Настройка конфигурации SQL Server 2005Express EditionВ некоторых главах книги вам потребуется доступ к SQL Server 2005 ExpressEdition (или SQL Server 2005) для создания и работы с базой данных North-wind Traders. Если вы используете SQL Server 2005 Express Edition, выполните

Page 14: Microsoft ASP.NET 2.0 AJAX

14 Введение

следующие действия для получения доступа к учетной записи пользователя,которая будет использоваться для выполнения упражнений данной книги:1. Войдите в Windows со своего компьютера, используя учетную запись с адми-

нистративными привилегиями.2. В меню Пуск (Start) выберите команду Все программы (All Programs) ► Стан-

дартные (Accessories) ► Командная строка (Command Prompt), чтобы открытьокно с приглашением командной строки.

3. Введите в приглашении командной строки следующую команду (с соблюде-нием регистра символов):sqlcmd -S Сервер\SQLExpress -Е

4. Замените Сервер именем своего компьютера.5. Чтобы определить имя компьютера, введите команду hostname в окне команд-

ной строки перед выполнением команды sqlcmd.6. Введите в приглашении 1> следующую команду (с квадратными скобками)

и нажмите Enter:sp_grantlogin \_Сервер\Пользователь

7. Замените Сервер именем своего компьютера, а Пользователь — именем ис-пользуемой учетной записи.

8. Введите в приглашении 2> следующую команду, затем нажмите Enter:

go

9. Если на экране появится сообщение об ошибке, проверьте правильность вво-да команды sp_grantlogin (в том числе наличие квадратных скобок).

10. Введите в приглашении 1> следующую команду (с квадратными скобками)и нажмите Enter:sp_addsrvrolemember [Сервер\Пользователь^, dbcreator

11. Введите в приглашении 2> следующую команду, затем нажмите Enter:

go

12. Если на экране появится сообщение об ошибке, проверьте правильность вво-да команды sp_ addsrvrolemember (в том числе наличие квадратных скобок).

13. Введите в приглашении 1 > следующую команду и нажмите Enter:exit

14. Закройте окно командной строки.15. Выйдите из системы.

Page 15: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 1 Структурные элементыприложений в стиле AJAXВ этой главе:I Сдвиг парадигмыI Объект XmlHttpRequestI Существующие прикладные среды AJAX в .NET

Сокращение AJAX происходит от слов «Asynchronous JavaScript and XML» («асин-хронный код JavaScript и XML»). Этим общим термином обозначаются высо-коинтерактивные приложения, быстро реагирующие на действия пользователя.Но о чем речь? Разве веб-приложения не были задуманы лет десять назад имен-но как интерактивные, быстро реагирующие и запускаемые при помощи специ-ального инструмента, называемого браузером? Что изменилось в наши дни?

Невероятный успех Интернета разжег аппетиты пользователей выше вся-ких ожиданий. Многолетняя потребность пользователей в еще более мощныхприложениях с веб-поддержкой заставляла архитекторов и разработчиков вне-дрять все больше функций на серверной платформе и в клиентских браузерах.В результате традиционная схема веб-приложения с каждым днем становитсявсе менее актуальной. Стало очевидно, что откладывать на будущее радикальныеизменения в архитектуре и модели программирования далее невозможно.

На данный момент отрасли требуется нечто большее, чем усовершенство-ванная и более мощная платформа, построенная по традиционным принципами правилам веб-приложений, — необходим настоящий сдвиг парадигмы. AJAXвоплощает новую парадигму для следующего поколения веб-приложений, и, ско-рее всего, этой парадигме суждено оставаться с нами как минимум в течениеближайшего десятилетия.

Если взглянуть на ситуацию с точки зрения разработчика, термином AJAXобозначается совокупность компонентов разработки, инструментов и методовсоздания высокоинтерактивных веб-приложений. В соответствии с парадигмойAJAX, веб-приложения в процессе работы обмениваются с веб-сервером данны-ми (а не страницами). Для конечного пользователя это означает более быстроеполучение обновленных данных и, что более важно, — существенное ускорениезагрузки и обновления страниц. Веб-приложения приближаются к классическимприложениям Microsoft Windows, поддерживают перетаскивание и асинхронныеоперации, быстро реагируют на действия пользователя, не мигают при перери-совке и не раздражают пользователя.

Page 16: Microsoft ASP.NET 2.0 AJAX

1 6 Глава 1. Структурные элементы приложений в стиле AJAX

Философия AJAX способствовала появлению нового поколения компонентови прикладных сред, каждая из которых была ориентирована на конкретную плат-форму, предоставляла заданный набор возможностей и интегрировалась с суще-ствующими прикладными средами. Microsoft Atlas представляет собой AJAX-до-полнение для платформы Microsoft ASP.NET 2.0.

ВНИМАНИЕВ действительности Atlas — нечто большее, чем реализация AJAX для платформыASP.NET. Бесспорно, концепции AJAX были заложены в основу Atlas. Однако сегодняAtlas воспринимается как значительное расширение платформы AST.NET, обеспе-чивающее типичную функциональность AJAX в сочетании с новыми расширеннымиклиентскими возможностями. В будущем Atlas и ASP.NET 2.0 объединятся в новойверсии ASP.NET. Таким образом, AJAX и Atlas не следует считать синонимами. Ско-рее, Atlas реализует «стиль AJAX» для платформы ASP.NET, однако при этом Atlas вы-ходит далеко за рамки типичной функциональности AJAX и обеспечивает клиентскуюинфраструктуру для построения веб-приложений нового уровня.

В этой главе мы сначала рассмотрим основные системные требования, общиедля всех решений и прикладных сред AJAX, а затем познакомимся с планамиMicrosoft относительно следующей версии Microsoft Visual Studio (кодовоеобозначение «Orcas»). В Orcas технология Atlas будет официально интегрирова-на с ASP.NET, остальными составляющими веб-платформы Microsoft и модельюприложений.

Сдвиг парадигмыВсе мы наблюдаем интересное, беспрецедентное явление (и вносим в него свойвклад) — Web претерпевает эпохальные изменения, обусловленные нашими дей-ствиями. Как бы радикально это ни прозвучало, но среда Web произвела перево-рот в концепции приложения. Всего восемь лет назад большинство разработчиковсчитало приложение чем-то слишком серьезным для превращения в беспоря-дочную смесь сценарного кода и разметки. В конце 1990-х годов считалось, чтоприложение должно быть оплачено кровью, потом, слезами и бесконечными се-ансами отладки. Для «настоящего» программиста в написании веб-приложенийне было ни чести, ни славы.

С тех пор среда Web прошла долгий путь развития. И хотя за 10 лет эволю-ции Web на стороне сервера сформировалась толстая прослойка абстракций,базовая структура — HTTP и страницы — осталась неизменной.

ПРИМЕЧАНИЕВпрочем, в конце 1990-х годов было спроектировано и создано немало веб-сайтов.За последующие годы некоторые из них невероятно выросли, превратились в столпысовременной мировой экономики и даже изменили наш подход к выполнению многихповседневных операций. Нужны примеры? Google, Amazon, eBay. И все же десять летназад люди, создавшие эти и другие приложения, принадлежали к наиболее передовойчасти разработчиков или были умными, дальновидными любителями.

Page 17: Microsoft ASP.NET 2.0 AJAX

Веб-приложения в наши дни 1 7

Исходная инфраструктура — простая, универсальная и эффективная — сталаопределяющим фактором стремительного успеха модели веб-приложений. Сле-дующее поколение веб-приложений по-прежнему будет базироваться на HTTPи страницах, однако содержимое страниц и возможности оборудования, рабо-тающего на стороне сервера, существенно изменятся. В результате впечатлениеот работы с веб-приложениями заметно изменится — последние приблизятсяк классическим Windows-приложениям для настольных систем.

Веб-приложения в наши дниРабота сегодняшних веб-приложений основана на отправке форм, заполненныхпользователем, на веб-сервер и последующем отображении разметки, возвращен-ной сервером. При обмене данными между браузером и сервером используетсяклассический протокол HTTP. Как известно, HTTP относится к числу протоко-лов без состояния; иначе говоря, каждый запрос никак не связан с предыдущим,а автоматическое сохранение информации состояния отсутствует (объекты со-стояния, известные всем нам, например, по ASP.NET, представляют собой абст-ракцию, реализуемую средой серверного программирования).

Обмен данными между браузером и веб-сервером происходит при помощиформ. С точки зрения пользователя пересылка осуществляется постранично. Ка-ждое действие пользователя, в результате которого серверу отправляется новыйзапрос, приводит к пересылке и отображению совершенно новой страницы (илиизмененной версии текущей страницы).

Небольшой анализ этой модели поможет выявить ее недостатки и те причи-ны, по которым сегодня стала необходима новая модель.

Отправка ввода в формахНа основании URL, введенного в строке адреса, браузер отображает страницу.Страница, в конечном счете, состоит из разметки HTML и содержит одну илинесколько форм HTML. Пользователь вводит данные, а затем приказывает брау-зеру отправить форму по URL, заданному для этой цели (URL действия).

Браузер преобразует заданный URL в IP-адрес и открывает сокет. ПакетHTTP, содержащий форму вместе со всеми полями, пересылается по каналусвязи заданному получателю. Веб-сервер принимает запрос и обычно переда-ет его внутреннему модулю для дальнейшей обработки. В конце процесса созда-ется пакет ответа HTTP, а возвращаемое браузером значение вставляется в телопакета.

Получение вывода в страницахПолучив запрос, например, на ресурс .aspx, веб-сервер передает его подсисте-ме ASP.NET для обработки и получает разметку HTML. Сгенерированная раз-метка включает все теги классической страницы HTML (<html>, <body>, <form>и т. д.). Исходный код страницы встраивается в ответ HTTP и помечается

Page 18: Microsoft ASP.NET 2.0 AJAX

1 8 Глава 1. Структурные элементы приложений в стиле AJAX

соответствующим типом MIME, чтобы браузер знал, как его следует обработать.В зависимости от типа MIME браузер выбирает дальнейшие действия.

Если ответ содержит страницу HTML, браузер полностью заменяет текущеесодержимое новой разметкой. Во время обработки запроса сервером на экранеотображается «старая» страница. Как только «новая» страница будет полностьюзагружена, браузер стирает изображение и выводит ее.

Достоинства и недостаткиОписанная модель хорошо работала в начале эпохи Web, когда содержимоевеб-страниц ограничивалось форматированным текстом, гиперссылками и не-большим количеством графики. Из-за успеха Web пользователи становились всеболее требовательными, а это заставляло разработчиков и дизайнеров создаватьвсе более сложный сервис и графику. В качестве примера возьмем рекламу.Сегодня на большинстве страниц (причем даже очень простых, как страницыблогов) присутствуют рекламные ротаторы, пересылающие клиенту немалыйобъем данных.

В результате страницы становятся тяжелыми и громоздкими — даже еслиупорно говорить о «расширенной функциональности», от этого ничего не изме-нится. Какой бы термин вы ни выбрали, веб-страницы современных приложенийименно таковы. Никто не поверит, что возможен возврат к минималистским,спартанским страницам HTML, существовавшим лет десять назад.

При действующей архитектуре веб-приложений каждое действие пользовате-ля требует полной перерисовки страницы. Как следствие, более тяжелые («ши-рокофункциональные») страницы медленнее воспроизводятся на экране, а ихпрорисовка сопровождается мерцанием. При большом наборе страниц крупно-го приложения (например, портала) такой механизм лишь вызовет раздражениеу конечного пользователя.

Хотя для построения страницы на сервере разработчик может воспользовать-ся целым рядом гибких архитектур (ASP.NET — всего лишь один из возможныхпримеров), с точки зрения клиента веб-страницы изначально проектировалисьв расчете на статичность и отсутствие изменений. В конце 1990-х годов этот ос-новополагающий факт изменился: сначала появился стандарт Dynamic HTML,затем модель объекта документа W3C (World Wide Web Consortium). В нашидни страница, отображаемая браузером, может модифицироваться с учетом изме-нений, вносимых исключительно на стороне клиента, в зависимости от действийпользователя (как будет показано далее, в AJAX и Atlas этот принцип получилдальнейшее развитие).

Стандарт Dynamic HTML стал серьезным шагом вперед, но одного его былонедостаточно для качественного изменения Web.

Веб-приложения завтраПерерисовку страниц было необходимо свести к минимуму. Для этой цели около1997 года появились первые примитивные формы сценарного удаленного вызова

Page 19: Microsoft ASP.NET 2.0 AJAX

Веб-приложения в наши дни 1 9

процедур (RPC, Remote Procedure Call). В частности, компания Microsoft со сво-ей технологией RS (Remote Scripting) стала одним из новаторов в этой области.

В RS для получения данных с удаленного URL были задействованы апплетыJava. URL предоставлял формализованный программный интерфейс и сериали-зацию данных, пересылаемых в обе стороны в строковом формате. На сторонеклиента компактная инфраструктура JavaScript принимала данные и активизиро-вала функцию обратного вызова, определяемую пользователем, для обновленияпользовательского интерфейса средствами Dynamic HTML или аналогичнымиметодами. Технология RS работала в Microsoft Internet Explorer 4.0, NetscapeNavigator 4.0 и последующих версиях.

Позднее компания Microsoft заменила апплет Java объектом COM с именемXmlHttpRequest и сняла большинство ограничений программного интерфейса,предоставляемого удаленным URL.

В то же время стараниями сообщества появился ряд аналогичных прикладныхсред, которые должны были поднять технологию RS на новый уровень и рас-ширить область ее практического применения. Апплет Java исчез и был замененобъектом XmlHttpRequest.

Что такое AJAX?Термин AJAX появился в 2004 году в сообществе Java. Первоначально он ис-пользовался для обозначения семейства взаимосвязанных технологий, реали-зующих различные формы удаленного исполнения сценариев. В наши дни всеразновидности удаленных сценарных технологий обычно помечаются префик-сом AJAX. Современные решения на базе AJAX для платформы Windows осно-ваны на объекте XmlHttpRequest.

В AJAX-приложениях сочетаются два противоречивых фактора. С однойстороны, приложение должно передавать пользователям свежие данные, по-лученные с сервера. С другой стороны, новые данные должны интегрироватьсяв существующую страницу без ее полного обновления.

Браузер обычно выдает новый запрос при отправке формы HTML, ини-циированной либо сценарием, работающим на стороне клиента, либо действиемпользователя (скажем, щелчком на кнопке). Получив ответ, браузер заменяетстарую страницу новой. На рис. 1.1 наглядно показана традиционная схема рабо-ты веб-приложений.

Основным фактором, заложенным в основу удаленного исполнения сцена-риев, является возможность выдачи внеполосных запросов HTTP. В данномконтексте под внеполосным вызовом понимается запрос HTTP, который выдает-ся за пределами встроенного модуля, обеспечивающего отправку форм HTTP(то есть вне традиционного механизма, показанного на рис. 1.1). Внеполос-ный вызов инициируется событием страницы HTML и обслуживается компо-нентом-посредником (proxy component). В новейших AJAX-решениях такимпосредником является объект XmlHttpRequest; в самых первых реализациях RSим был апплет Java.

Page 20: Microsoft ASP.NET 2.0 AJAX

2 0 Глава 1. Структурные элементы приложений в стиле AJAX

Браузер

Стандартный запрос HTTP

Рис. 1 .1. Браузер отправляет форму HTML и получает новую страницу,отображаемую на экране

Обновление страницКомпонент-посредник (например, объект XmlHttpRequest) отправляет обычныйзапрос HTTP и дожидается — синхронно или асинхронно — завершения его обра-ботки. Получив готовые данные ответа, посредник вызывает функцию обратноговызова JavaScript; эта функция должна обновить все части страницы, нуждаю-щиеся в обновлении. На рис. 1.2 показано графическое представление этой модели.

Внеполосный запрос HTTP (AJAX)

Браузер URL,л параметры

ПосредникЛ ПосредникЗапрос HTTP

JS лПосредник

DHTML лJS л

Посредник

Данные

Ответ HTTP

Рис. 1.2. Внеполосные вызовы обслуживаются компонентом-посредником, а функцияобратного вызова JavaScript обновляет все части страницы, зависящие

от полученных данных

Любой браузер умеет заменять старые страницы новыми, однако не все брау-зеры поддерживают объектную модель, представляющую текущее содержимоестраницы. В браузерах с поддержкой обновляемой объектной модели функцияобратного вызова JavaScript может обновить отдельные части старой страницы,не требуя ее полной перезагрузки.

Модель DOMСпецификация DOM (Document Object Model) определяет общий интерфейсобновления содержимого, структуры и стиля документов HTML и XML, не за-висящий от языка и платформы. Стандарт DOM получил признание и был ра-тифицирован комитетом W3C, поэтому сейчас он поддерживается все большим

Page 21: Microsoft ASP.NET 2.0 AJAX

Веб-приложения в наши дни 2 1

количеством браузеров. DOM определяет стандартный набор объектов для пред-ставления элементов, образующих документы HTML и XML. Совокупность этихобъектов образует стандартный интерфейс для работы с элементами страницHTML, или на более общем уровне — документов XML.

Следует заметить, что хотя первые работоспособные прикладные среды уда-ленного исполнения сценариев появились около десяти лет назад, ограниченнаяподдержка динамического изменения отображаемого документа в браузере тор-мозила массовое принятие таких технологий в масштабах отрасли. До сегодняш-него дня.

Роль широкофункционального браузераКак видно из рис. 1.2, модель AJAX предъявляет два ключевых требования к брау-зеру: наличие компонента-посредника и поддержка обновляемой модели DOM.В течение долгого времени оба требования выполнялись только передовыми,элитными браузерами (также часто встречается термин «широкофункциональ-ный браузер»). За прошедшие годы только компании, способные жестко контро-лировать возможности клиентских браузеров, могли выбрать модель AJAX длясвоих сайтов. Слишком долго термин «широкофункциональный» подразумевал«редко встречающийся», и для большинства коммерческих отраслей такие брау-зеры определенно не подходили.

Расширенную функциональность - в массы!Вероятно, благодаря какому-то редкому и совершенно непредсказуемому сочета-нию звезд около 90 % современных браузеров обладает встроенной поддержкойрасширенных возможностей, необходимых для модели AJAX. Internet Explorer,начиная с версии 5.0, Firefox, Netscape версии 6 и выше, Safari 1.1 и более новыхверсий, Opera 8.0 и различные мобильные устройства — все эти браузеры в пол-ной мере поддерживают модель программирования AJAX.

Впервые сложилась ситуация, когда широкофункциональный браузер пере-стал быть синонимом браузера с ограниченным кругом пользователей. Проек-тирование высокоинтерактивных веб-приложений, реализующих методы уда-ленного исполнения сценария, перестало быть недостижимой мечтой и сталосовершенно реальным делом.

Каждая платформа и каждая фирма-разработчик предлагает собственную при-кладную среду и инструментарий, но это не изменяет основополагающего фак-та — реализация стиля AJAX стала возможной в 90 % существующих браузеров.Это настоящий прорыв, благодаря которому сегодня можно создавать и распро-странять приложения, невозможные вчера.

Необходимые требованияЧто же именно требуется от браузера для поддержки функциональности AJAX?Как упоминалось ранее, браузер должен удовлетворять двум ключевым требова-ниям: поддержке посредников, чтобы клиентский код мог выдавать внеполосныевызовы HTTP, и поддержке обновляемой модели DOM.

Page 22: Microsoft ASP.NET 2.0 AJAX

2 2 Глава 1. Структурные элементы приложений в стиле AJAX

В настоящее время стандарт обновляемой модели DOM был ратифицированкомитетом W3C. Стандарт W3C для компонента-посредника пока находитсяв стадии разработки. Он воплощен в форме объекта XmlHttpRequest и представ-ляет собой интерфейс, предоставляемый браузером и позволяющий сценарномукоду выполнять клиентские функции HTTP — такие, как отправка данных формыили загрузка данных с удаленного веб-сайта. Последняя версия рабочего проектанаходится по адресу http://www.w3.o^R/XMLHttpRequest.

Также браузер должен поддерживать JavaScript и желательно CSS (каскад-ные таблицы стилей, Cascading Style Sheets). Выходит, что стиль AJAX доступенпрактически для любого разработчика и для 90 % аудитории Web, независимоот платформы. Инструменты, необходимые для работы AJAX, получили такое жеповсеместное распространение, как парсеры HTML/XML и обработчики JavaScript.Перефразируя лозунг популярной рекламной кампании, можно сказать: «AJAXздесь и сейчас!» А в том, что касается Windows и платформы ASP.NET, AJAXвоплощается в форме Microsoft Atlas (напомню: Atlas — нечто большее, чем про-стая реализация типичных функций AJAX вроде внеполосных вызовов и обнов-ляемых страниц; эта тема более подробно рассматривается в последующих гла-вах, начиная с главы 4).

Объект XmlHttpRequestОбъект XmlHttpRequest впервые появился в Internet Explorer 5.0. Этот внутрен-ний объект публикуется браузером для работы с его подсистемой исполнениясценариев. Сценарный код, входящий в клиентскую страницу (как правило, кодJavaScript), обращается к объекту и использует его функциональность.

Что касается функциональности (несмотря на префикс XML), объект XmlHttp-Request представляет собой компактную объектную модель для отправки сцена-рием обращений HTTP в обход браузера. Когда пользователь щелкает на кнопкеотправки формы или выполняет любое действие, приводящее к вызову методаsubmit объекта form модели DOM, браузер вмешивается в происходящее и берет последующую отправку запроса HTTP под свой полный контроль. С точки зре-ния пользователя, отправка запроса работает по принципу «черного ящика» с един-ственным видимым результатом: на экране появляется новая страница. Клиент-ский код сценария не может управлять процессом размещения и результатомотправки запроса.

Объект XmlHttpRequest дает возможность сценарному коду отправлять запро-сы HTTP и обрабатывать полученные ответы.

История и причиныОбъект XmlHttpRequest, созданный компанией Microsoft и вскоре принятый в Mo-zilla, в наши дни поддерживается большинством веб-браузеров. Как вы вскореубедитесь, его реализация в значительной мере зависит от браузера, хотя интерфейсверхнего уровня остается практически неизменным. По этой причине комитетW3C в настоящее время работает над точным описанием минимального набораобщих возможностей, основанного на существующих реализациях.

Page 23: Microsoft ASP.NET 2.0 AJAX

Объект XmlHttpRequest 2 3

ПРИМЕЧАНИЕОбъект XmlHttpRequest изначально поставлялся с Internet Explorer 5.0 в виде отдельно-го компонента (это было весной 1999 года). Во всех операционных системах Microsoft,выпущенных с того времени, он присутствует в виде интегрированного компонента.В частности, вы всегда найдете его на любом компьютере с Microsoft Windows 2000,Windows XP или более новой операционной системой.

Объект Internet ExplorerВ те времена, когда объект XmlHttpRequest только появился, в мире господствова-ла модель COM (Component Object Model), разработанная компанией Microsoft.Модель расширяемости программных продуктов и приложений базировалась натехнологии COM и реализовывалась с использованием компонентов COM. В кон-це 1990-х годов было совершенно правильно и естественно реализовать новыйкомпонент в виде объекта автоматизации COM, которому было присвоено имяMicrosoft.XmlHttp.

За последующие годы были выпущены разные версии того же компонента(даже со слегка различающимися именами), но во всех случаях исходная моделькомпонента оставалась неизменной — COM. Например, в Internet Explorer 6.0объект XmlHttpRequest поставляется в форме объекта COM. В чем проблема,спросите вы?

Объекты COM представляют собой внешние компоненты, для выполнениякоторых в веб-браузере необходимо специальное разрешение. В частности, дляинициализации объекта XmlHttpRequest и последующего использования любойфункциональности AJAX, построенной на его базе, клиентский компьютер дол-жен принимать компоненты ActiveX, помеченные как безопасные для использо-вания в сценариях (рис. 1.3).

Рис. 1.3. Окно свойств для изменения настроек безопасности в Internet Explorer

Page 24: Microsoft ASP.NET 2.0 AJAX

2 4 Глава 1. Структурные элементы приложений в стиле AJAX

Несомненно, компонент XmlHttpRequest безопасен. Но чтобы использоватьего, пользователь должен понизить общий уровень безопасности и принять всеостальные компоненты, объявленные «безопасными» для использования в сце-нариях, во всех посещаемых веб-сайтах.

ВНИМАНИЕВнутренняя реализация XmlHttpRequest отделена от реализации всех AJAX-сред(таких, как Microsoft Atlas). Во внутреннем представлении любая прикладная средав конечном итоге лишь обращается с вызовами к объекту, предоставляемому брау-зером.

Объект XmlHttpRequest в MozillaПоддержка XmlHttpRequest была принята в Mozilla сразу же после его первогопоявления в Internet Explorer 5.0. Однако в браузерах Mozilla XmlHttpRequestявляется частью объектной модели браузера и не зависит от внешних компо-нентов. Иначе говоря, браузеры семейства Mozilla — например, Firefox — публи-куют собственный объект XmlHttpRequest в сценарной подсистеме и не использу-ют внешний компонент COM, даже если последний установлен на клиентскомкомпьютере и является частью операционной системы. На рис. 1.4 представленыразные модели поддержки XmlHttpRequest в браузерах Internet Explorer (до вер-сии 6.0) и Mozilla.

Браузер Mozilla

MicrosoftXmlHttp

Браузер IE

Опубликованные объекты

Объекты JavaScriptОбъекты DOM

Запрос XmlHttp

Механизмисполнениясценариев

JavaScriptVBScript

Рис. 1.4. Сценарный компонент XmlHttpRequest предоставляется браузером в продуктахMozilla и реализуется в виде внешнего компонента СОМ в Internet Explorer (до версии 6.0)

Page 25: Microsoft ASP.NET 2.0 AJAX

Объектная модель HTTP 2 5

Как следствие, в браузерах Mozila объект XmlHttpRequest выглядит как интег-рированный («родной») объект JavaScript, а для создания его экземпляра приме-няется классический оператор new:

// Префикс XML в имени объекта должен быть записан прописными буквамиvar proxy = new XMLHttpRequestO;

В браузере Internet Explorer экземпляр объекта XmlHttpRequest создается с ис-пользованием «обертки» ActiveXObject:

var proxy = new ActiveXObjectC'Microsoft.XmlHttp");

Обычно прикладные среды в стиле AJAX определяют текущий браузер, а за-тем выбирают способ создания объекта в зависимости от результата проверки.

Излишне говорить, что функциональность XmlHttpRequest в браузерах Mozillaотличается большей безопасностью — хотя бы потому, что пользователю не при-дется изменять настройки безопасности в своем браузере.

XmlHttpRequest как интегрированныйобъект в Internet Explorer 7Объект XmlHttpRequest, который в браузерах Internet Explorer по историче-ским причинам всегда реализовывался в виде компонента COM, в InternetExplorer 7.0 наконец-то превратится в объект браузера. Все потенциальные про-блемы безопасности сразу отпадут, а прикладные среды AJAX могут быть пе-реведены на единый синтаксис создания объекта XmlHttpRequest независимо отбраузера:

var proxy = new XMLHttpRequestO;

Кроме того, это изменение в Internet Explorer 7.0 полностью отделит AJAX-функциональность (например, функциональность Microsoft Atlas) от среды с под-держкой ActiveX.

Объектная модель HTTPЯ довольно пространно описал объект XmlHttpRequest и его предполагаемоеповедение, но все еще не показал, как им пользоваться. В этом разделе рас-сматриваются свойства компонента, выполняемые им действия и подробностисинтаксиса.

Как упоминалось ранее, префикс XML в имени компонента ни о чем не говорити ни в коей мере не ограничивает возможности компонента. Несмотря на префиксXML, объект может использоваться как полноценный механизм автоматизацииисполнения запросов HTTP и управления ими, из клиентского кода, сгенериро-ванного страницами ASP.NET или неконтролируемыми (unmanaged) приложения-ми Visual Basic 6.0 и C++. Использовать объект COM XmlHttpRequest в приложе-ниях .NET бессмысленно, так как аналогичная функциональность присутствуетв пространстве имен System.Net .NET Framework.

Page 26: Microsoft ASP.NET 2.0 AJAX

2 6 Глава 1. Структурные элементы приложений в стиле AJAX

ВНИМАНИЕЕсли вы собираетесь применять Microsoft Atlas или другую AJAX-среду при построе-нии своих приложений, вам вряд ли придется иметь дело с объектом XmlHttpRequest,не говоря уже об его использовании в программном коде. Microsoft Atlas полностьюинкапсулирует объект, скрывая его от разработчиков страниц и приложений. Чтобынаписать приложение Atlas, даже самое сложное и хитроумное, вам не нужно ничегознать о XmlHttpRequest. Тем не менее знание основ XmlHttpRequest поможет лучшепонять платформу и повысит эффективность диагностики возникающих проблем.

Поведение и возможностиОбъект XmlHttpRequest предназначен для выполнения одной ключевой операции:отправки запросов HTTP. Запросы могут отправляться как синхронно, так и асин-хронно. В следующем фрагменте показан программный интерфейс объекта в томвиде, в каком он представлен в рабочем проекте W3C на момент написания книги:

interface XMLHttpRequest {function onreadystatechange;readonly unsigned short readyState;void open(string method, string url);void open(string method, string url, bool async);void open(string method, string url, bool async, string user);void open(string method, string url, bool async,string user, string pswd);void setRequestHeader(string header, string value);void send(string data);void send(Document data);void abortO;string getAllResponseHeadersO;string getResponseHeader(string header);string responseText;Document responseXML;unsigned short status;string statusText;

};

Операции с компонентом выполняются в два этапа. Сначала вы открываетеканал к URL, выбираете метод (GET, POST и т. д.) и указываете, должен ли за-прос быть отправлен асинхронно. На втором этапе задаются все необходимые за-головки, а запрос отправляется серверу. Если для запроса используется методPOST, методу send передается тело запроса.

При выполнении асинхронных операций метод send немедленно возвращаетуправление. Написанная вами функция onreadystatechange должна проверитьсостояние текущей операции и определить момент ее завершения.

Отправка запросаВ большинстве прикладных сред AJAX экземпляр объекта XmlHttpRequest длятекущего браузера создается кодом следующего вида:

var xmlRequest, е;try {

Page 27: Microsoft ASP.NET 2.0 AJAX

Объектная модель HTTP 2 7

xmlRequest = new XMLHttpRequestO ;}catch(e) {

try {xmlRequest = new ActiveXObjectC'Microsoft.XMLHTTP");

}catch(e) {}

}

Сначала мы пытаемся создать экземпляр внутреннего объекта XMLHttpRequest,а в случае неудачи выбираем способ с объектом ActiveX. Как видите, при созданииобъекта для браузера Internet Explorer перехватывается исключение. В InternetExplorer 7.0 такой код будет работать без изменений (в этом случае исключениене возникает).

Метод open готовит канал к передаче запроса; впрочем, физический сокет наэтой стадии еще не создается. Для выполнения команды POST необходимо до-бавить соответствующий заголовок типа содержимого.

Логический аргумент указывает, является ли операция асинхронной:xmlRequest.open("POST", url, false);xmlRequest.setRequestHeader("Content-Type",

"application/x-www-form-urlencoded");xmlRequest.send(postData);

Метод send открывает сокет и отправляет пакет. В предыдущем фрагментекода он возвращает управление только после полного получения ответа.

Для асинхронного запроса аналогичный код выглядит несколько иначе:xmlRequest.open("POST", url, true);xmlRequest.onreadystatechange = CallbackComplete;xmlRequest.setRequestHeader("Content-Type",

"application/x-www-form-urlencoded");xmlRequest.send(postData);

На место элемента CallbackComplete подставляется функция JavaScript, кото-рая получает и обрабатывает ответ, сгенерированный по отправленному запросу.

Обратите внимание: функция, указанная в поле onreadystatechange, вызыва-ется при всех изменениях состояния готовности. Допустимыми значениямиявляются целые числа от 0 до 4, которые означают соответственно «Запрос неинициализирован», «Метод open вызван успешно», «Метод send вызван успеш-но», «Прием данных» и «Ответ получен». Функция CallbackComplete обычно на-чинает свою работу с проверки состояния готовности.

Получение ответаОтвет доступен в двух форматах — физического текста и документа XML.

В состояниях готовности 0-2 свойство responseText остается пустым — дан-ные еще не приняты. При переходе в состояние 3 («Прием данных») свойствосодержит данные, полученные до настоящего момента, интерпретированные в за-данной кодировке символов. Если кодировка не указана, то по умолчанию ис-пользуется UTF-8.

Page 28: Microsoft ASP.NET 2.0 AJAX

2 8 Глава 1. Структурные элементы приложений в стиле AJAX

Свойство responseXml остается недоступным до того момента, когда запросбудет полностью принят и успешно разобран как документ XML. Если тело от-вета не содержит XML или разбор по какой-то причине завершается неудачей,свойство возвращает null. Обратите внимание на важное обстоятельство: доку-мент XML конструируется на стороне клиента после полного приема физиче-ского ответа HTTP.

Использование объекта XmlHttpRequestКак упоминалось ранее, вам не придется использовать объект XmlHttpRequestв своих AJAX-приложениях, независимо от используемой прикладной среды (на-пример, Atlas). И все же для полноты картины давайте кратко рассмотрим дейст-вия, необходимые для использования объекта в странице ASP.NET 2.0. Примеркода также может использоваться с ASP.NET 1.x.

Внеполосные вызовы из страниц ASP.NETДля веб-страницы, выдающей внеполосные вызовы, определяется одно или не-сколько триггерных событий, которые в результате обработки кодом JavaScriptвыдают запросы через объект XmlHttpRequest. Триггерными событиями могут бытьтолько события HTML, отслеживаемые реализацией DOM текущего браузера.

Код JavaScript должен инициировать обращение к удаленному URL и управ-лять им, как показано в следующем фрагменте:

<script type="text/javascript">function SendRequest(url, params){// Включение параметров в строку запросаvar pageUrl = url + "?outofband=true&param=" + params;// Инициализация объекта XmlHttpRequestvar xmlRequest, e;try {

xmlRequest = new XMLHttpRequestO ;}catch(e) {

try {xmlRequest = new ActiveXObjectC'Microsoft.XMLHTTP");

}catch(e) { }

}

// Подготовка к отправке синхронного запроса POSTxmlRequest.open("POST", pageUrl, false);xmlRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");xmlRequest.send(null);return xmlRequest;

}</script>

Функция в приведенном примере получает две строки — вызываемый URLи список параметров. Формат строки запроса никак не стандартизирован и можетпроизвольно изменяться в каждой конкретной реализации.

Page 29: Microsoft ASP.NET 2.0 AJAX

Использование объекта XmlHttpRequest 2 9

В нашем примере URL, заданный программистом, дополняется парой пара-метров. Первый параметр (outofband в нашем примере) представляет собой логи-ческий флаг, который указывает, должен ли запрос обрабатываться пользова-тельской функцией обратного вызова. Располагая этой информацией, целеваястраница сможет обеспечить правильную обработку запроса. Во втором парамет-ре (param в нашем примере) передаются входные параметры для кода, исполняе-мого на стороне сервера.

Код страницы выглядит примерно так:

<html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server">

<title>Testing Out-of-band</title></head>

<body><form id="Forml" runat="server">

<hl>Demonstrate Out-of-band Calls</hl><h2><^=Request.Url °1><I\\2><hr />

<asp:DropDownList runat="server" ID="EmployeeList" /><input id="Buttonl" type="button" value="Go Get Data"

onclick="MoreInfo()" /><hr /><span id="Msg" />

</form></body>

</html>

Класс программной логики (code-behind class) приведен в следующем лис-тинге:

public partial class _Default : System.Web.UI.Page{

protected void Page_Load(object sender, EventArgs e){

if (IsOutOfBandO)return;

if (!IsPostBack)PopulateListO;

}

private bool IsOutOfBandO{

if (Request.QueryString["outofband"] != null){

string param = Request.QueryString["param"].ToStringO ;Response.Write(ExecutePageMethod(param));Response.FlushO;Response.End();return true;

}return false;

}

Page 30: Microsoft ASP.NET 2.0 AJAX

3 0 Глава 1. Структурные элементы приложений в стиле AJAX

private void PopulateListO{

SqlDataAdapter adapter = new SqlDataAdapter("SELECT employeeid, lastname FROM employees","SERVER=(local);DATABASE=northwind;UID=...;");

DataTable table = new DataTableO;adapter.Fill(table);

EmployeeList.DataTextField = "lastname";EmployeeList.DataValueField = "employeeid";EmployeeList.DataSource = table;EmployeeList.DataBindO;

}

string ExecutePageMethod(string eventArgument){

return "You clicked: " + eventArgument;}

}

Некоторые моменты в этом листинге стоит упомянуть особо. Прежде всегообратите внимание на необходимость определения типа запроса (внеполосныйзапрос или обычная отправка). Затем посмотрите, как генерируется ответ. МетодIsOutOfBand проверяет поле outofband отправленной формы. Если поле outofbandприсутствует, то запрос обслуживается и завершается без прохождения по-следней части классического жизненного цикла запроса ASP.NET— событийизменения значений, возврата формы (postback) и т. д. Таким образом, внепо-лосные запросы быстрее обрабатываются и требуют передачи минимальногообъема данных.

Что должна делать страница при отправке внеполосного вызова? Как онаопределяет ответ? Большинство существующих AJAX-сред по-разному отве-чают на эти вопросы, поэтому можно сказать, что единого ответа на эти вопросыне существует. В общем случае вы определяете открытый программный интер-фейс, активизируемый при внеполосном вызове. В рассмотренном примере былсоздан метод ExecutePageMethod с фиксированным именем и сигнатурой, вы-вод которого интерпретируется как ответ на запрос. В нашем примере методполучает и возвращает строки; это означает, что для всех входных и выходныхпараметров должно быть возможно преобразование к строковому формату (се-риализация).

string param = Request.QueryString["param"].ToStringO ;Response.Write(ExecutePageMethod(param));Response.FlushO;Response.End();

В данном примере ответ внеполосного запроса полностью определяется вы-ходными данными метода. Никакие другие данные по запросу не возвращаются,а вся отправляемая информация ограничивается параметрами. В этой конкрет-ной реализации данные состояния отображения (view state) не отправляютсяи не возвращаются.

Page 31: Microsoft ASP.NET 2.0 AJAX

Использование объекта XmlHttpRequest 3 1

ВНИМАНИЕСкорее всего, вам никогда не придется писать подобный код. И все же учтите: мы толькочто рассмотрели минимальное, но эффективное описание базового механизма, общегодля всех прикладных сред, предоставляющих AJAX-функциональность. В каждой среде(например, Atlas, AJAX.NET) инкапсулируются многие технические детали и добавля-ются новые функции и возможности. Тем не менее на самом общем уровне библиотекиAJAX работают именно так.

Отображение результатовОстается сделать еще один шаг — что происходит на стороне клиента при полу-чении ответа на внеполосный запрос? Следующий фрагмент клиентского кодасвязывается с кнопкой, инициирует внеполосный вызов и обновляет пользова-тельский интерфейс:

function MorelnfoO{var empID = document.getElementByldC'EmployeeList").value:var xml = SendRequestC'default.aspx", empID);

// Обновление пользовательского интерфейсаvar label = document.getElementByldC'Msg");label.innerHTML = xml.responseText:

}

Каждый раз, когда пользователь щелкает на кнопке, на URL следующего видаотправляется внеполосный запрос (число 3 в примере URL обозначает код ра-ботника — рис. 1.5):

default.aspx?outofband=true&param=3

Рис. 1.5. «Ручное» программирование внеполосных запросов в ASP.NET 1 .х и ASP.NET 2.0

Page 32: Microsoft ASP.NET 2.0 AJAX

3 2 Глава 1. Структурные элементы приложений в стиле AJAX

Правильное отображение результатов в большинстве браузеров — задача неиз простых. Так, модель DOM в Internet Explorer поддерживает ряд нестандарт-ных сокращений, не работающих в других браузерах. Самая распространен-ная проблема — получение ссылок на элементы HTML с использованием методаdocument.getElementByld вместо прямого обращения по имени элемента. Напри-мер, следующий код работает в Internet Explorer, но не в Firefox и других браузе-рах семейства Mozilla:

// Msg - идентификатор тега <span>.// Команда работает только в IEMsg.innerHTML = xml.requestText;

Следовательно, для обновления страницы, отображаемой в данный момент настороне клиента, потребуется кросс-браузерный код JavaScript. В то же времядля обеспечения работоспособной и эффективной среды сервер должен сделатьряд допущений относительно клиента. По этой причине единственным разум-ным способом реализации функциональности AJAX остаются прикладные среды.Впрочем, разные среды могут предоставлять разные программные интерфейсына основе механизма, состоящего из единого набора составных частей.

Существующие прикладныесреды AJAX в .NETВ наши дни появилось немало прикладных интерфейсов (API), реализующихфункциональность AJAX в ASP.NET, причем один из них уже интегрированв ASP.NET 2.0. Другие API были созданы сторонними разработчиками или по-явились в проектах с открытым исходным кодом. В последней части настоящейглавы приводится краткий обзор таких API. Однако при этом я должен заме-тить, что если вашей основной средой разработки является ASP.NET, самым ло-гичным выбором будет Microsoft Atlas.

Хотя Microsoft Atlas также распространяется в виде отдельной надстройкидля ASP.NET 2.0, предполагается, что Atlas станет частью одной из следующихверсий ASP.NET, которой присвоено кодовое обозначение «Orcas». Бесспорно,Atlas является большим шагом в эволюции ASP.NET. Atlas происходит от двухAPI для ASP.NET — ASP.NET Script Callback и AJAX.NET (сейчас BorgWorXAJAX.NET), значительно расширяя их.

На момент написания книги другие компании (такие, как Telerik и Component-Art) также интегрировали функциональность AJAX в существующие компонен-ты для быстрой, полнофункциональной веб-разработки. В частности, компанияTelerik также выпустила обновление для своего набора компонентов, в результа-те чего большая часть компонентов стала совместима с Atlas.

В оставшейся части главы описаны способы использования Atlas на платфор-ме ASP.NET. Сначала мы познакомимся с подсистемой ASP.NET Script Callback,входящей в ASP.NET 2.0, и сравним ее с BorgWorX AJAX.NET (библиотека с от-крытым исходным кодом). После этого станет очевидно, что для создания совре-менных приложений с расширенными возможностями потребуется прикладная

Page 33: Microsoft ASP.NET 2.0 AJAX

ASP.NET Script Callback 3 3

среда, спроектированная специально под «стиль AJAX» — а еще лучше, если онабудет хорошо интегрирована с «базовой» (underlying) платформой.

Если вы программируете с использованием компонентов ASP.NET, вероятно,вам стоит остановить свой выбор на Microsoft Atlas. Если вы пользуетесь услугамипакета элементов с поддержкой ASP.NET, скорее всего, в его следующей версиипоявится интегрированная поддержка функциональности Atlas. Так или иначе,будущее веб-программирования на платформе ASP.NET тесно связано с AJAX.

ASP.NET Script CallbackASP.NET 2.0 содержит интегрированный API, называемый ASP.NET Script Call-back, для реализации внеполосных вызовов к URL текущей страницы. В этомAPI внеполосный запрос выглядит как запрос страницы особого рода. В нем со-стояние отображения передается вместе с исходными полями ввода. Для переда-чи дополнительной информации в тело запроса включаются дополнительныеполя ввода. Оказавшись на сервере, запрос проходит через обычный конвейермодулей HTTP и доводит ожидаемую последовательность событий на сторонесервера до фазы предварительного построения (pre-rendering).

Непосредственно перед фазой предварительного построения выполняетсяметод страницы, возвращаемое значение сериализуется в строку, а строка воз-вращается клиенту. Фаза построения никогда не наступает, а состояние отобра-жения передается обратно без обновления.

Код на стороне клиентаВнеполосный вызов ASP.NET начинается с выполнения функции JavaScript,предоставленной системой. Как правило, эта функция связывается с обработчи-ком события уровня страницы — такого, как щелчок на кнопке или изменениевыбранной строки в раскрывающемся списке. Для наглядности рассмотрим кон-кретный пример.

Представьте веб-страницу, на которой отображается информация о работни-ке. Пользователь выбирает имя из списка и щелкает на кнопке, чтобы получитьдополнительную информацию. Чтобы механизм внеполосного вызова успешноработал, кнопка не должна быть кнопкой отправки (submit button); в противномслучае произойдет обычная отправка данных с полным обновлением страницы.Возьмем следующую разметку:

<asp:dropdownlist id="cboEmployees" runat="server"DataTextField="lastname" DataValueField="employeeid" />

<input type="button" runat="server" id="buttonTrigger"value="More Info">

Пользователь выбирает элемент из списка и щелкает на кнопке, чтобы полу-чить дополнительную информацию. Обработчик события onclick кнопки добав-ляется динамически при обработке страницы на сервере. Такие вещи уместно де-лать при обработке события Page_Load:

protected void Page_Load(object sender, EventArgs e){

Page 34: Microsoft ASP.NET 2.0 AJAX

3 4 Глава 1. Структурные элементы приложений в стиле AJAX

if (!IsPostBack){

// Заполнение спискаcboEmployees.DataSource = GetEmployeeListO;cboEmployees.DataBind();

// Построить средствами ASP.NET строку с функцией Javascript,// вызываемой для инициирования внеполосного вызоваstring rpc = ClientScript.GetCallbackEventReference(

this,"document.forms[0].elements['cboEmployees'].value","UpdatePage","null","null",false);

// Инициирование внеполосного вызова кнопкойstring js = String.Format("javascript:{0}", rpc);buttonTrigger.Attributes["onclick"] = js;

}}

private Collection<Employee> GetEmployeeListO{

}

ASP.NET Script Callback предоставляет собственный JavaScript API для ин-капсуляции всех необходимых обращений к XmlHttpRequest. Вам как разработчи-ку не обязательно знать этот API во всех деталях. Вместо этого следует напра-вить все внимание на программный интерфейс метода GetCallbackEventReferenceобъекта Page.ClientScript. Метод получает параметры, используемые при вызове,и возвращает строку с исходным кодом JavaScript, предназначенную для внедре-ния в страницу. Когда страница передается пользователю, кнопка, инициирую-щая внеполосный вызов, связывается со следующим сценарием:

<input name="buttonTrigger" type="button" id="buttonTrigger"value="More Info"onclick="javascript:WebForm_DoCallback(' Page',

document.forms[0].elements['cboEmployees'].value,UpdatePage,null, null, false)" />

Где определяется WebForm_DoCallback? Сценарий хранится в ресурсах сборкиsystem.web и связывается со страницей при помощи динамически сгенерирован-ной директивы включения сценария:

<script src="/ProAspNetAdv/WebResource.axd?d=...&t=..."type="text/javascript"></script>

В странице, предоставленной пользователю, этот элемент располагается непо-средственно за открывающим тегом <form>. Не стоит и говорить, что WebForm_DoCallback вызывает объект XmlHttpRequest и управляет запросом HTTP.

Page 35: Microsoft ASP.NET 2.0 AJAX

ASP.NET Script Callback 3 5

Метод GetCallbackEventReferenceАргументы, передаваемые методу GetCallbackEventReference, определяют, как дол-жен активизироваться и работать нижележащий механизм обратного вызова:

public string GetCallbackEventReference(Control target,string argument,string clientCal1 back,string context,string clientErrorCallback,bool useAsync)

Смысл каждого параметра описан в табл. 1.1.

Таблица 1.1. Параметры функции GetCallbackEventReference

Параметр Описание

target Задает целевой объект, то есть объект на стороне сервера, которыйбудет обрабатывать запрос. Таким объектом может быть страницаASP.NET или любой серверный элемент, определенный в странице.Целевой объект должен реализовать интерфейс ICallbackEventHandler.Если целевой объект не реализует необходимый интерфейс,инициируется исключение

argument Задает входные параметры метода, вызываемого на серверев ответ на получение вызова. Если методу должны передаватьсянесколько параметров, разработчик обязан упаковать их в однустроку. Содержимое параметра без какой-либо дополнительнойобработки передается серверному методу, обслуживающему запрос

clientCallback Задает имя функции JavaScript на стороне клиента, которойбудет передан результат вызова. Любые данные, возвращаемыесерверным методом (даже строковые), передаются без какой-либодополнительной обработки указанной функции JavaScript.Если функция не определена или недоступна для клиентскойстраницы, происходит ошибка сценария

context Сценарий, выполняемый на стороне клиента перед инициированиемобратного вызова. Результат выполнения сценария передаетсяобработчику события на стороне клиента

clientErrorCallback Имя функции JavaScript на стороне клиента, которой будет переданрезультат при возникновении ошибок в ходе выполнения метода настороне сервера. Функция clientCallback в этом случае не вызывается

useAsync Если параметр равен true, вызов выполняется асинхронно, еслиfalse — синхронно. По умолчанию используется значение false

Вооружившись этой информацией , вернемся к коду, который мы кратко рас-сматривали ранее:

// Вызывается из Page_Loadstring rpc = ClientScript.GetCallbackEventReference(

this,"document.forms[0].elements['cboEmployees'].value",

Page 36: Microsoft ASP.NET 2.0 AJAX

3 6 Глава 1. Структурные элементы приложений в стиле AJAX

"UpdatePage","null","null",false);

Целевым объектом вызова является страница; это означает, что класс про-граммной логики страницы должен реализовать интерфейс ICallbackEventHandler.Аргумент, передаваемый методам интерфейса, представляет собой результат за-данного выражения JavaScript:

document.forms[0].elements['cboEmployees'].value

Ничто не гарантирует, что в свойствах серверного элемента будут содержать-ся самые свежие данные, обновленные с учетом последних изменений на сторонеклиента. Чтобы от клиента на сервер заведомо передавались обновленные дан-ные, необходимо указать выражение JavaScript для их выборки в явном виде.

Интерфейс ICallbackEventHandlerВ клиентском коде страницы, использующей ASP.NET Script Callback, с каждымсобытием HTML связывается фрагмент кода JavaScript, сгенерированный систе-мой. Этот код JavaScript использует внутренние обращения к XmlHttpRequest длявыдачи внеполосных вызовов. Код JavaScript также ссылается на другой фраг-мент JavaScript, используемый для обновления страницы результатами, получен-ными от сервера. Но что происходит на сервере при выдаче вторичного запроса?Какой метод страницы при этом выполняется?

ASP.NET Script Callback определяет интерфейс с именем ICallbackEventHandler;этот интерфейс может быть реализован любым серверным объектом, который яв-ляется целевым для внеполосных вызовов. Таким объектом может быть либо стра-ница, либо любой из ее дочерних элементов. Интерфейс состоит из двух методов:

public interface ICallbackEventHandler{

string GetCallbackResultO;void RaiseCallbackEvent(string eventArgument);

}

Исполнение внеполосного вызова делится на две фазы: подготовку и получе-ние результатов. Сначала вызывается метод RaiseCallbackEvent для подготовкик удаленному выполнению кода. Метод GetCallbackResult вызывается на болеепоздней стадии жизненного цикла запроса, когда runtime-среда ASP.NET долж-на сгенерировать ответ для браузера. Традиционно метод RaiseCallbackEvent со-храняет аргумент во внутренней переменной, а весь содержательный код выпол-няется в GetCallbackResult. Впрочем, это всего лишь общепринятая практика.Следующий листинг показывает, как происходит получение и передача инфор-мации клиенту:

private int _empID;void ICallbackEventHandler.RaiseCallbackEvent(string argument){

Int32.TryParse(argument, out _empID);}

Page 37: Microsoft ASP.NET 2.0 AJAX

ASP.NET Script Callback 3 7

string ICal1backEventHandler.GetCal1backResult(){

// Получение дополнительной информации о заданном работникеEmployeelnfo emp = GetEmployeeDetai1s(_empID);

// Подготовка ответа для клиента: используется строковый формат// с разделением данных запятыми.// Вы сами выбираете формат возвращаемой строки. Этот формат// должен быть известен функции обратного вызова JavaScript.string[] buf = new string[6];buf[0] = emp.ID.ToStringO;buf[l] = emp.FirstName;buf[2] = emp.LastName;buf[3] = ешр.Title;buf[4] = ешр.Country;buf[5] = ешр.Notes;_results = String.Join(",", buf);return ;

}

Возвращаемые данные должны быть представлены в виде строки. Если исход-ные данные представляют собой управляемый объект, он сериализуется в строку.Затем на стороне клиента строка разбирается, и из нее извлекается вся важнаяинформация.

ASP.NET Script Callback: все вместеПредполагается, что метод GetCallbackResult возвращает строку, которая представ-ляет ответ на запрос. Возвращаемая строка передается функции JavaScript, обнов-ляющей страницу. Клиентская функция обратного вызова выглядит примерно так:

<script language="javascript">function UpdateEmployeelnfoOesponse, context){

// Разбиение ответа на массив строкvar о = response.split(',');

// Получение ссылок на обновляемые элементы страницьvar e_ID = document.getElementByldC"e_ID");var e_FName = document.getElementById("e_FNaine");var e_LName = document.getElementById("e_LName");var e_Title = document.getElementById("e_Title");var e_Country = document.getElementById("e_Country");var e_Notes = document.getElementById("e_Notes");

// Обновление элементов страницы данными с сервераe_ID.innerHTML = о[0];e_FName.innerHTML = о[1];e_LName.innerHTML = о[2];e_Titie.innerHTML = o[3];e_Country.innerHTML = o[4];e_Notes.innerHTML = o[5];

}</script>

За присутствие такой функции в клиентской странице отвечает автор страницы.

Page 38: Microsoft ASP.NET 2.0 AJAX

3 8 Глава 1. Структурные элементы приложений в стиле AJAX

Основные фактыВ общем и целом программный интерфейс ASP.NET Script Callback неудобен.Он скрывает от разработчика многие внутренние технические детали, но при этомтребует хороших навыков использования JavaScript и немалого объема шаблон-ного серверного кода. Серверный код необходим для связывания элементовHTML с обработчиками событий на стороне клиента, а также для публикациипрограммного интерфейса, вызываемого со стороны клиента.

Каждый запрос содержит копию исходного состояния отображения, а на серве-ре воссоздается последнее заведомо работоспособное состояние. Другими словами,исходные значения всех полей ввода на странице, отображаемой в настоящиймомент (без учета изменений, внесенных перед внеполосным вызовом), переда-ются серверу вместе со всеми параметрами серверного метода.

Все внеполосные вызовы обрабатываются как обычные запросы на возвратданных вплоть до фазы предварительного построения; это означает, что в хо-де обработки инициируются все стандартные серверные события: I nit, Load, Load-Complete и т. д. Перед фазой предварительного построения происходит подго-товка и выполнение обратного вызова. После выполнения серверного методаобработка запроса немедленно прекращается. Состояние отображения не обнов-ляется в соответствии с изменением страницы после внеполосного вызова и невозвращается клиенту.

Преимущество ASP.NET Script Callback состоит в том, что этот механизминтегрирован в ASP.NET и легко инкапсулируется в серверных элементах. На-пример, элемент TreeView в ASP.NET 2.0 использует его для развертыванияузлов.

Тем не менее механизм ASP.NET Script Callback не свободен от целого рядасерьезных недостатков. В частности, серверный метод ограничивается фиксиро-ванной сигнатурой, получает и возвращает только строки. Конечно, в строкуможно поместить любые данные, однако сериализацию и десериализацию объек-тов вам придется выполнять самостоятельно. Кроме того, страница, основаннаяна ASP.NET Script Callback, может иметь только одну конечную точку дляудаленных вызовов. Это означает, что если клиентская страница должна обра-щаться к одной удаленной странице с двумя разными вызовами, вам придетсявключить в реализацию интерфейса ICallbackEventHandler логику выбора вызы-ваемого метода.

Библиотека AJAX.NETВ сущности, ASP.NET Script Callback представляет собой низкоуровневый API,предоставляющий в распоряжение программиста очень тонкую абстрактнуюпрослойку, функции которой сводятся к автоматическому построению сценар-ного кода для инициирования вызова. Для эффективной реализации внеполос-ных вызовов в сценариях уровня приложения необходима библиотека, котораябы скрывала все технические подробности обмена данными HTTP и предостав-ляла дополнительный сервис более высокого уровня.

Page 39: Microsoft ASP.NET 2.0 AJAX

Библиотека AJAX.NET 3 9

AJAX.NET — популярная библиотека с открытым исходным кодом, создающаяабстрактное представление для механизма XmlHttpRequest. Чтобы использоватьбиблиотеку, необходимо внести изменения в файл web.config и зарегистрироватьв нем специализированный обработчик HTTP. Обработчик предоставляет допол-нительные функции (такие, как сериализация объектов). В частности, обработ-чик гарантирует, что любой управляемый объект .NET, возвращаемый сервер-ным методом, будет сериализован в динамически созданный объект JavaScript,который без проблем используется на стороне клиента.

Давайте переработаем предыдущий пример с использованием библиотекиAJAX.NET.

ПРИМЕЧАНИЕИсходная версия библиотеки AJAX.NET была разработана для ASP.NET 1.x МайкломШварцем (Michael Schwarz), а затем была обновлена для ASP.NET 2.0. За дополни-тельной информацией обращайтесь на сайт http://www.ajaxpro.info. Недавно разработкабиблиотеки была прекращена и возобновилась в виде проекта с открытым исходнымкодом под руководством BorgWorX (http://www.borgworx.net).

Подготовка библиотекиДля использования библиотеки AJAX.NET потребуется сборка AJAX.dll, котораянаходится в глобальном кэше сборок (GAC) или в папке Bin приложения. Затемв файл web.config включается запись обработчика HTTP:

<httpHandlers><add verb="POST,GET" path="AJAX/*.ashx"

type="AJAX.PageHandlerFactory, AJAX" /></httpHandlers>

В результате все запросы к URL, соответствующим шаблону AJAX/*.ashx, пе-редаются обработчику AJAX.NET.

Обратите внимание: вам не придется создавать в приложении подкаталог AJAXсо всеми страницами, вызываемыми через AJAX.NET. Библиотека используетспециализированный обработчик HTTP (компонент AJAX.PageHandlerFactory)для перехвата запросов к ресурсам с заданными именем. Клиентская структураAJAX.NET гарантирует, что все URL, к которым производятся обращения со сто-роны клиента, обладают соответствующим форматом.

Обработчик HTTP автоматически внедряет в поток ответа весь клиентскийкод, необходимый для инициирования внеполосных вызовов. С точки зрения раз-работчика для использования библиотеки AJAX.NET в приложении необходимолишь включить приведенную ранее секцию в файл web.config.

Клиентский кодКлиентская страница AJAX.NET содержит код JavaScript, инициирующий вне-полосные вызовы. Представьте страницу, которая рассматривалась ранее дляASP.NET Script Callback. На странице находится кнопка для получения до-полнительной информации о выбранном работнике. С кнопкой (которая, как

Page 40: Microsoft ASP.NET 2.0 AJAX

4 0 Глава 1. Структурные элементы приложений в стиле AJAX

уже говорилось ранее, не является кнопкой отправки данных!) связываетсякод следующего вида:

<script type="text/javascript">function GetCustomerDetailО{

var customerlD = document.getElementByldC'customerlD");var response = TestPage.GetCustomerByID(customerID.value);var oCustomer = response.value;

if (oCustomer.Type == "UnknownCustomer"){

alertC'Customer not found");}else{

var fn = document.getElementByldC'firstName");var In= document.getElementByldC'lastName");fn.innerHTML = oCustomer.FirstName;ln.innerHTML = oCustomer.LastName;

}}

</script>

Как видите, функция JavaScript обращается с вызовом к вроде бы несущест-вующему клиентскому объекту (объект TestPage), а объект JavaScript использует-ся для обработки возвращаемого значения (переменная oCustomer). Где определя-ется метод TestPage.GetCustomerBylD? И где определяется прототип переменнойoCustomer? В обоих случаях ответ один: в классе программной логики.

Серверный кодКласс программной логики страницы AJAX.NET должен удовлетворять паретребований. Во-первых, он предоставляет для класса страницы один или не-сколько открытых методов, помеченных атрибутом [AJAXMethod]. Во-вторых, со-бытие Page_Load должно регистрировать один или несколько типов в инфра-структуре AJAX.

public partial class TestPage : System.Web.UI.Page{

protected void Page_Load(object sender, EventArgs e){

Uti1ity.RegisterTypeForAJAX(typeof(TestPage));Uti1ity.RegisterTypeForAJAX(typeof(Samples.Customer));Uti1ity.RegisterTypeForAJAX(typeof(Samples.UnknownCustomer));

}

[AJAXMethodO"public Customer GetCustomerByID(string customerlD){

// Здесь размещается код выборки информации о работнике// из базы данныхswitch (customerlD)

Page 41: Microsoft ASP.NET 2.0 AJAX

Библиотека AJAX.NET 4 1

{case "1":

return new CustomerC'John", "Doe");case "3":

return new CustomerC'Jim", "Idontknowthisguy");default:

return new UnknownCustomerO;}

}}

Серверная страница воспроизводится на стороне клиента через объект Java-Script, имя которого совпадает с именем класса страницы — TestPage в нашемпримере. Любой серверный метод, помеченный атрибутом [AJAXMethod], определя-ется как метод этого объекта JavaScript. Автоматически генерируемое тело методавыдает внеполосный вызов к соответствующему серверному методу с использо-ванием XmlHttpRequest. Серверный метод может вернуть любой объект, зарегист-рированный в инфраструктуре AJAX; в отличие от ASP.NET Script Callback онни в коей мере не ограничивается возвратом строк. Каждый объект, зарегистри-рованный в AJAX, строится как объект JavaScript, определение которого затемсвязывается с клиентской страницей.

В результате вы можете обращаться с удаленными вызовами к любому количе-ству методов на стороне сервера и использовать собственные объекты для пере-дачи информации, реализуя своего рода «HTTP-вызовы с сильной типизацией».

Библиотека AJAX.NET: все вместеПодготовительная настройка решений AJAX.NET достаточно проста. Сначалапосредством редактирования файла web.config к приложению подключается пе-рехватчик AJAX.NET. Затем пишется встроенный код JavaScript для управлениявнеполосным вызовом. Каждый вызов обращен к объекту JavaScript, представ-ляющему открытый интерфейс серверной страницы ASP.NET. Когда к страницепоступает первый запрос, обработчик страниц AJAX.NET автоматически внедря-ет сценарный код с определением «объекта страницы» JavaScript. Каждый методэтого объекта ссылается на соответствующий серверный метод.

Возвращаемое значение серверного метода инкапсулируется в объекте Java-Script, определяемом в AJAX. Чтобы получить возвращаемое значение, обратитеськ свойству value полученного объекта. Возвращаемое значение серверного методапредставляет собой объект JavaScript, который имитирует открытый интерфейсреально возвращаемого типа данных. Другими словами, серверный метод возвра-щает тип .NET, а клиентский код получает соответствующий объект JavaScript.Этот процесс называется сериализациейJSON (JavaScript Object Notation).

Основные фактыAJAX.NET обладает рядом преимуществ по сравнению с ASP.NET Script CallbackAPI. Методы, вызываемые со стороны клиента, помечаются специальным ат-рибутом. Такой способ обеспечивает наибольшую гибкость при определении

Page 42: Microsoft ASP.NET 2.0 AJAX

4 2 Глава 1. Структурные элементы приложений в стиле AJAX

открытого интерфейса сервера, вызываемого со стороны клиента. Кроме того,возможность регистрации серверных типов, используемых на стороне клиента,позволяет реализовать пересылку данных с сильной типизацией. Инфраструкту-ра AJAX.NET сериализует типы .NEТ в объекты JavaScript, и наоборот.

AJAX.NET перехватывает и заменяет стандартный механизм обработки за-просов ASP.NET (обработчик страниц). Как следствие, вы не будете полу-чать классические серверные события ASP.NET типа Init и Load, а состояниеотображения не будет автоматически передаваться с каждым внеполоснымзапросом. Однако при этом запросы AJAX.NET по-прежнему обрабатываютсяruntime-системой HTTP ASP.NET, то есть с запросом работают различные мо-дули, зарегистрированные в конвейере HTTP, включая управление состояни-ем сеанса, управление ролями и аутентификацию. Дело в том, что запрос по-глощается и обрабатывается обработчиком AJAX.NET HttpHandler, поэтому нанего распространяются общие принципы, управляющие обработкой запросовв ASP.NET.

Прикладные среды на базе AJAXПо мере того как стиль программирования AJAX получает признание как сле-дующий крупный шаг в области веб-разработки, вступают в действие два оче-видных фактора. Во-первых, для разработчиков приложений очень важно иметьмодель программирования, которая бы не слишком сильно отличалась от ужезнакомых им моделей. Разработчики должны относительно быстро переходитьна AJAX. Однако быстрый переход возможен только в том случае, если новаяприкладная среда является расширением старой. Но во-вторых, новая приклад-ная среда должна предоставлять в распоряжение разработчика широкофункцио-нальные и эффективные готовые компоненты и службы, сводящие к минимумувлияние таких сложных и объективно существующих факторов, как написаниекросс-браузерного сценарного кода, модели программирования на стороне сервераи сериализация данных. Вместо автономных библиотек — таких, как ASP.NETScript Callback и AJAX.NET (по крайней мере, в исходной версии проекта), — разработчики отдают предпочтение прикладным средам и пакетам компонентовASP.NET, обеспечивающим расширенную поддержку AJAX.

Технология Microsoft Atlas, представленная на Конференции профессиональ-ных разработчиков в 2005 году, представляет собой надстройку для платформыASP.NET 2.0. Она станет одним из столпов следующей версии ASP.NET (Orcas).Atlas воплощается в форме нового семейства серверных элементов, для которыхза счет использования новых runtime-функций становится возможной полная ин-теграция программирования на стороне клиента и сервера.

Вся оставшаяся часть книги полностью посвящена архитектуре и моделипрограммирования Atlas. По этой причине будет полезно кратко познакомитьсяс парой коммерческих продуктов, которые обеспечивают AJAX-функциональ-ность, а в будущем с большой вероятностью будут обладать интегрированнойподдержкой Atlas.

Page 43: Microsoft ASP.NET 2.0 AJAX

Прикладные среды на базе AJAX 4 3

Web.UI (ComponentArt)Компонент Callback является частью Web.UI — пакета элементов ASP.NET ком-пании ComponentArt. Он добавляет функциональность AJAX к ряду другихкомпонентов семейства Web.UI. Кроме того, он способен наделить поддержкойAJAX практически любой из существующих элементов ASP.NET.

Компонент CallBack, как и его «родной» аналог из Atlas (компонент UpdatePanelподробно рассматривается в главе 3), способен работать в обход стандартногожизненного цикла страницы для ускоренного выполнения логики на сторонесервера, а также поддерживать обновленную информацию о состоянии всех эле-ментов ASP.NET, содержащихся в странице, за счет использования состоянияотображения.

Компонент CallBack ориентирован на серверо-центрическую модель програм-мирования, но пока не обладает встроенными функциями для разработки клиен-то-центрических решений (обращения к веб-службам, методы страниц или при-вязка данных на стороне клиента). Впрочем, в будущих версиях Web.UI дляASP.NET будет реализована полная поддержка Atlas. За дополнительной инфор-мацией обращайтесь на сайт http://www.componentart.com.

r.a.d.ajax (Telerik)Элемент r.a.d.ajax компании Telerik представляет собой новую прикладную средуAJAX; заявка на его патент сейчас находится в стадии рассмотрения. Он позво-ляет включить поддержку AJAX в любое приложение ASP.NET без программи-рования. Главной целью этого продукта является устранение всех сложностей,связанных с программированием на JavaScript при построении AJAX-приложе-ний; это позволяет разработчикам использовать новую технологию без значи-тельных затрат времени и сил на ее освоение.

Задача решается инкапсуляцией механизма AJAX и всей примыкающей логи-ки в компонентах ASP.NET, настройка которых в Visual Studio 2005 может осу-ществляться на визуальном уровне, с помощью удобных построителей (builders).В результате разработчик пишет обычное приложение, основанное на возвратеданных, и легко превращает его в AJAX-приложение; при этом ему даже не при-ходится писать какой-либо код JavaScript или серверный код.

Главным достоинством этого продукта является технология автоматическойзамены функций возврата данных элементов страницы обратными вызовамиAJAX (в настоящее время решается вопрос с ее патентованием). В результатеэлемент «AJAX’ифицируется» и начинает выдавать обратные вызовы без вме-шательства со стороны пользователя — без специального кода JavaScript и про-изводимых «вручную» обращений к XmlHttpRequest. Эта технология способнанаделить поддержкой AJAX любые стандартные элементы ASP.NET, элемен-ты Telerik для ASP.NET (пакет r.a.d.controls) и большинство элементов сто-ронних разработчиков (за дополнительной информацией обращайтесь по адресуhttp://www.telerik.com/).

Page 44: Microsoft ASP.NET 2.0 AJAX

4 4 Глава 1. Структурные элементы приложений в стиле AJAX

Прикладная среда Telerik r.a.d.ajax включает следующие компоненты:I AJAX Panel — универсальный контейнер, включающий поддержку AJAX. Всеэлементы, размещенные внутри контейнера, начинают выдавать обратныевызовы вместо возврата данных.

I AJAX Manager — компонент, который позволяет на стадии конструированияуказать, какие элементы страницы должны инициировать обратные вызовыи какие элементы нуждаются в соответствующем обновлении.

I AJAX Timer — компонент, выполняющий обратные вызовы AJAX с заданнымиинтервалами.Кроме того, встроенная поддержка AJAX присутствует во всех компонентах

пользовательского интерфейса Telerik. Например, поддержка AJAX задействова-на во внутренней работе всех компонентов для работы с данными из пакетаTelerik r.a.d.controls; тем самым обеспечивается производительность, близкаяк производительности приложений реального времени. Режим AJAX включает-ся при помощи одного свойства.

Среда Telerik полностью сохраняет жизненный цикл страниц ASP.NET, чтокрайне важно для правильной работы приложения. Состояние отображения,проверка событий и сценарии клиентской стороны полностью сохраняются, какпри обычном возврате данных. Все данные форм автоматически отправляютсясерверу для обработки.

Прикладная среда Telerik r.a.d.ajax представляет собой комплексное решение,позволяющее даже начинающему разработчику ASP.NET создавать сложные веб-приложения с поддержкой AJAX, схожие с Microsoft Office Outlook Web Access.

ЗаключениеСамые прозорливые разработчики сообщества занимаются разработками набазе интерактивных веб-технологий с конца 1990-х годов. За прошедший периодпоявились различные технологии (например, Microsoft Remote Scripting и дру-гие разработки — как коммерческие, так и бесплатные), однако это не привелок формированию критической массы — как по распространению, так и по ис-пользованию. А может быть, критическая масса накопилась, но ей не хватало де-тонатора в виде сверхпопулярного приложения. Другим фактором, замедлившимпринятие более совершенных клиентских технологий, было отсутствие кросс-браузерной поддержки.

Сегодняшняя ситуация в корне отличается от той, которая существовала все-го три или четыре года назад. Сейчас около 90 % браузеров поддерживают всеминимальные требования для реализации интерактивных веб-приложений, из-вестных как приложения AJAX. Кроме того, комитет W3C стандартизировалобъект XmlHttpRequest, на базе которого строится большинство существующихплатформ для AJAX. Следующее поколение веб-приложений будет основано нановом механизме: этим механизмом будут уже не формы, отправляемые присмене страниц (или по крайней мере не только они), а индивидуальные запросыданных и динамические обновления отображаемых страниц.

Page 45: Microsoft ASP.NET 2.0 AJAX

Заключение 45

ASP.NET как серверная технология, ориентированная на создание веб-стра-ниц, не упускает возможность предоставить эту столь востребованную функцио-нальность. Первой попыткой создания API для построения страниц «в стилеAJAX» был механизм ASP.NET Script Callback. Построенный по образцу класси-ческих событий возврата данных, он оказался излишне тяжеловесным и не-достаточно гибким. Проект с открытым исходным кодом AJAX.NET был болееудачным решением: он превосходил Script Callback по широте возможностей, погибкости и прямолинейности модели программирования. Тем не менее обеимтехнологиям были присущи два главных недостатка — отсутствие широкофунк-циональной клиентской объектной модели, компенсирующей различия междуреализациями DOM в разных браузерах, и отсутствие четкой границы междуклиентскими и серверными аспектами программирования.

Microsoft Atlas определяет ближайший путь развития AJAX-приложений с по-зиций платформы ASP.NET. Atlas интегрирует стиль AJAX с существующей мо-делью приложений ASP.NET. Результатом такой интеграции является знакомаямодель программирования со значительно расширенной и обогащенной функ-циональностью.

Page 46: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 2 Структурные элементы AtlasВ этой главе:I Архитектура AtlasI Программная модель AtlasI Пример страницы Atlas

Microsoft Atlas — прикладная среда, внедряющая функциональность в стиле AJAXна платформу Microsoft ASP.NET 2.0. В отличие от других аналогов, среда Atlasпроектировалась как составная часть ASP.NET, и как следствие, она идеальноинтегрируется с существующей платформой и моделью приложения. Техноло-гия Atlas будет полностью интегрирована в следующую версию Microsoft VisualStudio и наряду с поддержкой LINQ и Model-View-Controller будет заложенав основу будущей платформы ASP.NET, выход которой ожидается в 2007 году (задополнительной информацией о LINQ и ее роли в контексте следующей версии.NET Framework обращайтесь по адресу http://msdn.microsoft.com/data/ ref/linq).

С самого начала вы должны думать об Atlas как о «родной» части платформыASP.NET, а не как о «приделанной» (и более или менее ненавязчивой) внешнейбиблиотеке. В контексте ASP.NET подсистеме Atlas отведена вполне понятнаяи четко определенная роль. Она придает «изюминку» всей платформе, превра-щая ее в высокопроизводительную платформу для веб-приложений в стилеAJAX. Благодаря Atlas разработчики смогут строить интерактивные, кросс-браузерные веб-приложения, базирующиеся на существующих стандартах — таких, как Dynamic HTML, JavaScript, CSS (Cascading Style Sheets) и, наконец,XmlHttpRequest. Взяв на вооружение Atlas, вы наконец-то сможете писать веб-приложения, работающие в браузерах Microsoft Internet Explorer, Firefox, Netscapeи Safari, отличающиеся универсальностью и простотой развертывания.

Atlas вносит усовершенствования как на стороне клиента, так и на сторонесервера. Богатый набор компонентов, элементов и функций упрощает AJAX-про-граммирование, и что еще важнее, делает его полностью прозрачным для разра-ботчиков ASP.NET. На стороне клиента Atlas использует клиентскую инфра-структуру пользовательского интерфейса (UI) и модель сценарных компонентов (script component model - см. http://www.microsoft.com/technet/scriptcenter/resources/scriptshop/default.mspx) для быстрого и эффективного проектирования богатой,интерактивной функциональности. По мере того как платформа Atlas развивает-ся по пути полной интеграции с веб-платформой Microsoft, новые инструментыдля разработчиков и дизайнеров будут создаваться и интегрироваться в следую-щую версию Visual Studio.

Page 47: Microsoft ASP.NET 2.0 AJAX

Архитектура Atlas 4 7

Разумеется, столь богатый сценарный инструментарий (конструкторы эле-ментов, мастера, средства диагностики и трассировки) скроет от пользователябольшую часть базовых механизмов. Тем не менее знание основных структур-ных блоков Atlas необходимо как для понимания целей и возможностей сущест-вующих высокоуровневых компонентов, так и для создания новых.

Архитектура AtlasС архитектурной точки зрения прикладная среда Atlas состоит из двух элемен-тов: библиотеки клиентских сценариев и набора серверных расширений, интег-рирующих Atlas в ASP.NET. Библиотека клиентских сценариев написана полно-стью на JavaScript, а следовательно, работает с любым современным браузером.Так как Atlas является расширением ASP.NET, среда полностью интегрированас серверными службами и элементами ASP.NET. Как следствие, разработчикимогут создавать широкофункциональные веб-страницы на базе Atlas практиче-ски теми же методами, которые применяются при разработке классических сер-верных страниц ASP.NET.

Atlas в сочетании с ASP.NET предлагает комплексную программную модель,которая распространяется как на клиентскую, так и на серверную среду. Темне менее область применения Atlas не ограничивается серверной платформойASP.NET и даже не привязывается к ней.

Если говорить точнее, платформа Atlas совершенно независима от сервераи может работать с любым веб-сервером, включая Apache. Библиотека клиент-ских сценариев Atlas может использоваться на любом клиенте и на любом серве-ре. Разумеется, если вы пытаетесь использовать Atlas на платформе другого веб-сервера, то вам придется предоставить все необходимые службы и компонентыAtlas в формате, действительном для этой серверной платформы. Например,при использовании веб-сервера Apache с поддержкой PHP (PHP: HypertextPreprocessor) потребуются как минимум менеджер сценариев Atlas и прокси-ге-нератор, написанные в виде модулей PHP. На платформе ASP.NET эти компо-ненты становятся доступными после установки Atlas.

Мы еще вернемся к этому моменту позднее в настоящей главе.

Подготовка AtlasПрежде чем переходить к подробному рассмотрению архитектуры Atlas, давайтекратко познакомимся с некоторыми стандартными аспектами установки, настрой-ки и запуска приложений Atlas.

Установка AtlasЧтобы начать работать с Atlas, прежде всего следует загрузить новейшую версиюприкладной среды. Информацию о том, какой пакет вам потребуется, можно най-ти на сайте http://atlas.asp.net — официальной домашней странице Atlas. Пакет,загруженный с сайта, содержит отладочную и окончательную версии библиоте-ки сценариев Atlas и все необходимые двоичные файлы. Если на вашем компь-ютере установлена любая версия Visual Studio 2005, пакет также настраивает

Page 48: Microsoft ASP.NET 2.0 AJAX

4 8 Глава 2. Структурные элементы Atlas

интегрированную среду разработки (IDE) так, чтобы в ней отображался готовыйшаблон проекта Atlas (рис. 2.1).

Пакет Atlas в формате MSI (Microsoft Windows Installer) копирует на вашкомпьютер ряд файлов в следующую папку:

%DRIW%:\Program Fi 1 es\Microsoft ASP.NET\Atlas\v2.0.50727\Atlas

Рис. 2 . 1 . Шаблон проекта Atlas, появляющийся при создании новой веб-страницы

В частности, копируется сборка с именем Microsoft.Web.Atlas.dll и файл web.config с включенной поддержкой Atlas. Эта версия конфигурационного файласодержит все записи, необходимые для нормального выполнения приложенийAtlas. Сборка Atlas также включает группу файлов JavaScript (.js), образующихбиблиотеку клиентских сценариев. Примерное содержимое папки после установ-ки Atlas показано на рис. 2.2.

Мастер установки спрашивает вашего разрешения на установку шаблоновпроектов Visual Studio для конкретных языков и на регистрацию нового расши-рения .asbx. Оба действия не являются обязательными.

Расширение .asbx идентифицирует мостовые файлы Atlas. Мостовые файлыпредставляют собой компоненты, взаимодействующие с веб-службами вне вашегоприложения. Типичный пример использования файлов .asbx — получение дан-ных с других веб-сайтов для создания гибридных сайтов (mash-ups). Содержи-мое таких сайтов формируется посредством объединения информации, получен-ной из сторонних источников.

Если ваше приложение не получает данные из внешних веб-источников, ре-гистрировать расширение .asbx не обязательно. Мостовые файлы будут болееподробно рассмотрены в главе 6.

Page 49: Microsoft ASP.NET 2.0 AJAX

Архитектура Atlas 4 9

Рис. 2.2. Содержимое пакета Atlas

Развертывание приложений AtlasСамый простой способ создать приложение Atlas — выбрать шаблон проектаVisual Studio 2005 (рис. 2.1). Visual Studio 2005 копирует runtime-сборку Atlas изустановочной папки в папку Bin нового сайта. В то же время Visual Studio вклю-чает в проект файл web.config со всеми параметрами, необходимыми для запускаприложений Atlas.

Чтобы включить поддержку Atlas в существующее приложение ASP.NET илисоздать приложение Atlas без шаблона проекта Visual Studio 2005, выполнитеследующие действия.

Сначала добавьте runtime-сборку Atlas (Microsoft.Web.Atlas.dll) в папку Binприложения (при включении ссылки на сборку Atlas это делается автоматиче-ски). Учтите, что сборка обычно находится в папке

%DRIME%:\Program Fi 1 es\Microsoft ASP.NET\Atlas\v2.0.50727\Atlas

Затем отредактируйте файл web.config приложения и введите все необходимыепараметры (они будут описаны позднее, в разделе «Пример страницы Atlas»).

ПРИМЕЧАНИЕКомпания Microsoft сообщила первую информацию об Atlas на Конференции профес-сиональных разработчиков в 2005 году. С того времени каждые несколько недель пуб-ликуется бюллетень CTP (Community Technology Preview). В выпуске CTP за март2006 года компания Microsoft также опубликовала лицензию Go-Live, разрешавшуюиспользовать инструментарий Atlas для реализации AJAX-функциональности в рабо-чих проектах. Иначе говоря, вам не обязательно ждать выхода окончательной версииAtlas, чтобы заняться разработкой собственных решений; и разумеется, не нужно до-жидаться, пока поддержка Atlas будет включена в Visual Studio версии Orcas, котораявыйдет в 2007 году. Технология Atlas доступна здесь и сейчас!

Page 50: Microsoft ASP.NET 2.0 AJAX

5 0 Глава 2. Структурные элементы Atlas

Базовые компонентыПрикладная среда Atlas состоит из клиентской и серверной части. Клиентскаябиблиотека JavaScript используется приложениями в основном для управленияпользовательским интерфейсом страниц и для вызова серверных компонентов.Серверные компоненты генерируют ответ для клиента и выдают заранее опреде-ленный клиентский сценарий, который интегрируется с клиентской библиотекой,а иногда и расширяет ее. Серверная часть Atlas включает веб-службы, специаль-ные элементы и инфраструктуру JSON (JavaScript Object Notation). (Техноло-гия обмена данными JSON будет описана позднее в этой главе.)

Клиентская библиотекаКлиентская библиотека Atlas состоит из набора файлов JavaScript (*.js), под-ключаемых из клиентских страниц в случае надобности. Эти файлы *.js уста-навливаются как файлы с исходным кодом при установке Atlas на компьютерразработчика. На рабочий компьютер они не копируются, потому что они такжевнедряются в сборку Atlas, а страницы ссылаются на все необходимые сценар-ные файлы как на ресурсы сборки.

Клиентская библиотека содержит объектно-ориентированные и кросс-браузер-ные расширения языка JavaScript, такие как классы, пространства имен, насле-дование и типы данных. В ней также определяется (по большей части закрытая)версия библиотеки базовых классов .NET, включающая поддержку построите-лей строк, регулярных выражений, таймеров и трассировки. Ключевой частьюклиентской библиотеки Atlas является сетевой уровень, который берет на себявсе сложности асинхронных вызовов с использованием XmlHttpRequest. Сетевойуровень позволяет клиентской странице взаимодействовать с веб-службами и веб-страницами посредством внеполосных вызовов.

Клиентская библиотека Atlas также содержит поддержку таких функций,как перетаскивание, всплывающие окна, задержка указателя мыши над объек-том, а также группу элементов с поддержкой привязки данных полностью настороне клиента, навигации и автозаполнения. Такие элементы могут вставлять-ся в исходный код страниц с использованием JavaScript (в дополнение к новомудекларативному синтаксису XML Script).

Серверные компонентыТехнология Atlas появилась как расширение ASP.NET, а ASP.NET является плат-формой разработки на стороне сервера. По этой причине в Atlas входит наборсерверных компонентов, включая веб-службы и элементы управления. С однойстороны, вы можете программировать эти компоненты со стороны клиента и обнов-лять текущую страницу без полного обновления; с другой стороны, программнаямодель большей частью остается неизменной. В этом отношении (по крайнеймере, в том, что касается базовой функциональности) срок освоения Atlas оказы-вается на удивление коротким.

Встроенные веб-службы Atlas предоставляют клиентским страницам наборстандартных функций ASP.NET, в числе которых профили пользователей, член-

Page 51: Microsoft ASP.NET 2.0 AJAX

Базовые компоненты 5 1

ство в группах, роли и глобализация. Серверные элементы Atlas выглядят какклассические серверные элементы ASP.NET, но в отличие от последних онивыдают дополнительный сценарный код. Код расширяет возможности элементаза счет (необязательного) использования функций, предоставленных клиентскойбиблиотекой Atlas. Большинство элементов Atlas имеет близкие аналоги средисуществующих элементов ASP.NET — таких, как кнопки, надписи, текстовые поляи элементы проверки данных. Другое важное подмножество серверных элемен-тов Atlas выдает код JavaScript для связывания аспектов поведения клиентскихсценариев с элементами разметки HTML. Код поведения находится в клиент-ской библиотеке; некоторые серверные элементы позволяют управлять связыва-нием аспектов поведения с определенными видами разметки (например, связы-ванием автозаполнения с конкретным элементом TextBox).

Элементы Atlas ни в чем принципиально не отличаются от классических сер-верных элементов ASP.NET. После того как они будут включены в Visual StudioOrcas, вы сможете работать с элементами Atlas в конструкторе страниц точнотак же, как с обычными элементами. К моменту выхода Visual Studio Orcas неостанется реальных различий между элементами ASP.NET и элементами Atlas.

JSONВ связи с расширением применения внеполосных вызовов в веб-приложениях воз-никает новая проблема с передачей все более и более сложных данных. Пробле-ма не сводится к простой сериализации, для которой в .NET Framework и другихплатформо-зависимых прикладных средах уже имеется готовое решение. Задачасериализации при внеполосных вызовах не сводится к простому обеспечениюкросс-платформенности; в ней также задействованы разные логические уровнис участием сильно различающихся инструментов и языков. При внеполосныхвызовах данные передаются на сервер и обратно. Но сторона клиента представ-лена браузером (без учета мобильных устройств), для которого «родным» фор-матом данных является JavaScript. Сторона сервера представлена веб-сервером,способным работать на разных комбинациях аппаратных и программных плат-форм, с некоторой прикладной средой веб-приложений.

Формат JSON набирает популярность как способ передачи структурирован-ных данных в Web. Этот формат обмена данными основан на подмножестве язы-ка JavaScript, а его полное описание можно найти по адресу http://www.json.org.JSON относительно легко читается человеком, разбирается и генерируется ком-пьютером. Для описания данных в нем используются две универсальные струк-туры данных — коллекции и массивы, в той или иной форме поддерживаемыевсеми современными языками программирования и библиотеками классов.

Текстовый формат JSON совершенно не зависит от языка программирования,хотя в нем применяются многие условные обозначения, унаследованные от язы-ков семейства C.

Клиентская инфраструктура JSON сериализует объект JavaScript в форматобмена данными и пересылает его по каналу связи получателю, находящемусяна стороне сервера. Получатель, привязанный к конкретной платформе, разбира-ет поток данных и строит платформо-зависимый объект. Аналогично, серверная

Page 52: Microsoft ASP.NET 2.0 AJAX

5 2 Глава 2. Структурные элементы Atlas

инфраструктура JSON может взять любой платформо-зависимый объект и се-риализовать его в формат обмена данными. На стороне клиента поток данныхбыстро преобразуется в объект JavaScript. С точки зрения .NET Framework и Atlasпотребуется проанализировать внутреннюю структуру классов и создать для нихподходящие «обертки» JavaScript.

Инфраструктура JSON реализована практически во всех средах на базе AJAX.Atlas не является исключением. Впрочем, как упоминалось в главе 1, в ASP.NET 2.0Script Callback поддержка JSON отсутствует.

ПРИМЕЧАНИЕОдно время XML рекламировался как «единый язык» Web; ведь он создавался спе-циально для того, чтобы разработчики и проектировщики могли упаковывать данныеи передавать их совершенно независимо от платформы. В наши дни ту же роль частоотводят JSON (технология, не зависящая от XML). В чем различия? JSON и XML ре-шают одну и ту же задачу. Формат XML сложнее и запутаннее, но он лучше подходитдля описания данных, к которым применяются трансформации XSLT.Для низкоуров-невых данных предпочтение отдается формату JSON — он « легче» по объему переда-ваемых данных, проще читается людьми и разбирается компьютерами.

Atlas на других серверных платформахВеб-приложения по определению не должны зависеть от серверной платформы.Тем не менее это не значит, что комбинация оборудования и программногообеспечения сервера вообще ни на что не влияет. Это утверждение остается ис-тинным даже в том случае, когда благодаря Atlas и другим прикладным средамна базе AJAX фокус приложения перемещается на сторону клиента.

Как упоминалось ранее, в приложениях Atlas клиентский код может смеши-ваться с серверным, а для построения страниц необходима специализированнаяподдержка на сервере. Если на веб-сервере используется ASP.NET и IIS, эта под-держка распространяется бесплатно и загружается вместе с Atlas. На других сер-верных платформах ее придется строить отдельно.

Необходимые функцииМинимальный набор функций для поддержки Atlas на серверных платформах,не связанных с ASP.NET, включает доступ к веб-службам и прикладным службам,а также распознавание браузера. Кроме того, страницы Atlas могут использоватьширокофункциональные элементы управления для выдачи разметки и сценарногокода. На других серверных платформах такие элементы могут не существовать. Да-вайте немного подробнее рассмотрим функции, необходимые для поддержки Atlas.

ASP.NET автоматически генерирует клиентского посредника для веб-служ-бы, ссылка на которую включена в страницу ASP.NET Atlas. Посредник автома-тически сериализует объекты .NET в JavaScript и обратно. Аналогичная инфра-структура должна быть построена и на других платформах, хотя для некоторыхконкретных платформ удается воспользоваться сериализатором JSON.

Страницы ASP.NET Atlas включают инициализирующий компонент Script-Manager, который автоматически распознает возможности текущего браузера

Page 53: Microsoft ASP.NET 2.0 AJAX

Atlas на других серверных платформах 5 3

и вносит соответствующие поправки в пересылаемый код JavaScript. Если вы ис-пользуете веб-сервер, отличный от IIS (Internet Information Server), в сочетаниис ASP.NET, код для выполнения этих операций придется добавить самостоятельно.

Наконец, ASP.NET предоставляет набор прикладных служб, которые могутвызываться удаленно клиентскими страницами: аутентификация, кэширование,пользовательские профили и т. д. Если эта функциональность будет сочтена по-лезной, вероятно, она будет реализована и для других платформ.

Приложения Atlas и РНРСтраницы Atlas представляют собой обычные веб-страницы, написанные с ис-пользованием некоторого языка и модели программирования, будь то ASP.NET,классический вариант ASP, Perl, Rails или PHP. С позиций веб-программирова-ния у каждого языка имеется своя предпочтительная программная модель, и на-оборот; тем не менее базовая схема остается неизменной. Технология Atlas пол-ностью интегрирована с платформой ASP.NET, но результат ее применения всеравно представляет собой веб-приложение.

Если Atlas используется за пределами ASP.NET, вы не сможете пользовать-ся серверными элементами. Впрочем, элементы всего лишь помогают быстросгенерировать широкофункциональный, сложный сценарный код без изученияJavaScript. Серверные элементы являются ключевым компонентом прикладнойсреды ASP.NET, но аналогичные компоненты можно создать с другими моделямидля других серверных сред. Чтобы использовать Atlas, допустим, с PHP, всю инте-грацию придется реализовать самостоятельно — это и есть основной объем работы.

Если вас заинтересует пример, демонстрирующий написание страниц Atlasс PHP на веб-сервере Apache, загляните в блог Шанку Нийоги (Shanku Niyogi)по адресу http://www.shankun.com. Приложение содержит папку кода с напи-санным на PHP сериализатором JSON, базовым классом веб-службы и прокси-генератором сценарного кода. Пример показывает, как создать веб-службу Atlasс использованием PHP. Файл PHP ссылается на базовый класс веб-службы и объ-являет класс, производный от базового класса веб-службы Atlas. Вот небольшойфрагмент этого файла:

<?phprequire_once("AtlasPhp/AtlasService.php");class AutoComplete extends AtlasService{

function GetWords($prefixText, $count){

return $results;}

}$service = new AutoComplete();$service->ProcessRequest(null);?>

Если вас заинтересует полный исходный код, а также различные сообщенияи комментарии, обратитесь по адресу http://www.shankun.com/atlasphp.aspx.

Page 54: Microsoft ASP.NET 2.0 AJAX

5 4 Глава 2. Структурные элементы Atlas

Программная модель AtlasAtlas предлагает два основных подхода к веб-разработке: серверо-центрическийи клиенто-центрический. В обоих случаях создается широкофункциональноевеб-приложение с большим количеством кода JavaScript; различается только ис-пользуемая программная модель.

Серверо-центрическая модель позволяет последовательно наращивать готовыеприложения AJAX-расширениями пользовательского интерфейса. Также можносоздавать новые приложения на базе AJAX, с классическим серверо-центриче-ским подходом. Основная часть пользовательского интерфейса и логики прило-жения на сервере пишется на Microsoft Visual Basic или C#. Таким образом, объемнеобходимого кода JavaScript минимален или близок к нулю. Выбор серверо-цен-трической модели позволяет разработчикам ASP.NET наделить веб-приложениеинтерактивными возможностями при чрезвычайно высокой скорости обучения.

Однако настоящая сила Atlas (и решений на базе AJAX вообще) проявляетсяпри полноценном использовании JavaScript и модели DOM браузера в клиенто-центрической модели. В этом варианте открывается гораздо больше возможно-стей по обогащению и расширению интерактивности пользовательского интер-фейса. Вы можете строить гибридные приложения, приблизить веб-приложениепо скорости реакции на ввод пользователя к настольным приложениям и т. д.Впрочем, не все разработчики достаточно уверенно чувствуют себя с JavaScriptи DOM, поэтому в Atlas существует две модели программирования.

Итак, Atlas предоставляет отличную прикладную среду на базе AJAX для раз-работок на основе серверо- и клиенто-центрических подходов. Ни одна модельне является предпочтительной во всех ситуациях; выбор модели зависит от ва-ших личных навыков и предпочтений, а также специфики решаемой задачи.

Например, гибридное приложение значительно труднее реализовать без при-менения JavaScript и DOM. С другой стороны, если вас интересует лишь час-тичное обновление страницы, инициируемое по таймеру или условиям временивыполнения, вам не обязательно возиться с кодом JavaScript — задача успешнорешается применением серверных элементов Atlas.

Серверо-центрическая программная модельНа рис. 2.3 представлена серверо-центрическая программная модель. Как обыч-но, изначально отображаемая клиентская страница состоит из HTML, CSS и не-большого объема сценарного кода. Она генерируется на сервере и передаетсяклиенту при помощи серверных элементов и логики, содержащейся в классахпрограммной логики страницы. Вся логика выражается с использованием управ-ляемого кода и языков .NET (таких, как C#).

На стороне сервера в Atlas работает целый ряд специализированных серверныхэлементов, классов и прикладных служб, доступных для клиентского кода. В стра-ницу, передаваемую пользователю, встраиваются сценарные обработчики дляклиентских событий страницы. Эти обработчики пишутся на JavaScript и гене-рируются серверными элементами Atlas. Из их кода инициируются внеполосные

Page 55: Microsoft ASP.NET 2.0 AJAX

Программная модель Atlas 5 5

вызовы, которые передают клиенту новую разметку и сценарный код для обнов-ления отдельных частей отображаемой страницы.

Браузер

Исходное построение

(пользовательский1Представление

(HTMUCSS)

1 ^

интерфейс + сценарный код)

Входные данные

—"ЧЧ- (обновленныйинтерфейс +

сценарный код)

Приложение ASP.NET

Страницы

Логикастраницы

(управляемыйкод)

Сценарная среда Atlas

Средакомпонентов/

пользовательскогоинтерфейса,элементыуправления

Клиентскиеприкладныеслужбы

ASP.NET

Страничнаясреда,

серверныеэлементы

Прикладныеслужбы

Рис. 2.3. Серверо-центрическая программная модель Atlas

В этой модели Atlas ближе всего подходит к классической модели програм-мирования ASP.NET. Просто разработчик использует другой набор серверныхэлементов, а эти элементы, в сочетании со страничной средой Atlas, выполняютвсю работу. Страницы получаются гораздо более интерактивными, чем в клас-сической модели ASP.NET, и не требуют «физического контакта» разработчикас JavaScript.

Страничная среда AtlasДля работы Atlas необходима работающая на стороне сервера runtime-среда, со-стоящая из компонентов — таких, как компонент ScriptManager. Он гарантирует,что страница будет содержать все необходимые сценарные блоки, адаптирован-ные для текущего браузера. Наличие такого компонента помогает авторам стра-ниц, а также разработчикам элементов в написании элементов с поддержкой Atlas.Компонент ScriptManager стоит за частичными и пошаговыми обновлениями стра-ниц; он отвечает за включение ссылок на сценарный код в клиентскую страницудля вызова веб-служб, отладочных функций и сервиса времени выполнения.

Любая страница, использующая прикладную среду Atlas, должна содержатьровно один экземпляр элемента ScriptManager. Элемент также можно разместитьна главной странице, в результате чего он станет доступным для всех производ-ных страниц.

Page 56: Microsoft ASP.NET 2.0 AJAX

5 6 Глава 2. Структурные элементы Atlas

Страничная среда Atlas, представленная в первую очередь элементом Script-Manager, выполняет ряд функций: включение режима частичного построениястраниц, загрузка полной или облегченной версии ядра Atlas, загрузка необя-зательных сценариев Atlas, определение веб-служб, которые могут вызыватьсястраницей.

Прикладные службыAtlas поддерживает пару стандартных прикладных служб, при помощи которыхклиентские страницы обращаются к специфической функциональности на сторо-не сервера. Прикладные службы оформлены в виде веб-служб, но рассматриватьих нужно именно как сервис приложений. Речь идет о службе аутентификациии службе профилей.

Служба аутентификации представляет собой «обертку» для операций регист-рации входа и проверки данных пользователя. Вызывая методы службы и пре-доставляя регистрационные данные, клиентская страница может через внеполос-ный вызов определить, прошел ли пользователь аутентификацию, и получитьмандат (ticket) в случае успешной аутентификации. Служба аутентификациивзаимодействует со стандартными провайдерами ролей и принадлежности.

Служба профилей читает словарь пользовательских данных в формате, оп-ределяемом моделью профильных данных в файле web.config. Для выполнениясвоих функций служба профилей взаимодействует со стандартным провайдеромпрофилей ASP.NET.

Серверные элементыСамые первые версии Atlas столкнулись с критикой со стороны сообщества про-граммистов, потому что для построения улучшенных приложений требовалосьвладение JavaScript и навыками асинхронного программирования. В последую-щих версиях компания Microsoft значительно изменила программную модель.Сегодня при построении приложений Atlas используются элементы, объектнаямодель и события, уже знакомые разработчикам по ASP.NET. Кроме того, разра-ботчик может воспользоваться новыми элементами ASP.NET (календари, рас-ширенные текстовые поля и т. д.), действующими как серверные «обертки» дляклиентских компонентов Atlas.

Эти серверные элементы выдают разметку HTML с серверным кодом, спо-собным использовать клиентскую библиотеку Atlas и инициировать внеполос-ные вызовы. Красота модели в том, что вам как автору страницы не придетсябеспокоиться об изучении JavaScript. «Умные» элементы с поддержкой Atlas самивыдадут весь необходимый код.

Другой ключевой аспект серверной стороны Atlas — расширители элемен-тов. Расширители (extenders) представляют собой компоненты Atlas, добавляю-щие специальные клиентские возможности к любому существующему элементуASP.NET. К числу необязательных возможностей относятся всплывающие под-сказки (ToolTips), автозаполнение и перетаскивание. Они реализуются в видеблока сценарного кода, связанного с расширяемым элементом ASP.NET. Расши-рители и серверные элементы Atlas будут рассматриваться в главе 4.

Page 57: Microsoft ASP.NET 2.0 AJAX

Программная модель Atlas 5 7

Клиенто-центрическая программная модельНа рис. 2.4 показана клиенто-центрическая программная модель Atlas, объеди-няющая типичную статическую разметку и таблицы стилей со специальным пове-дением, приближенным к функциональности настольных приложений. В отличиеот страниц, создаваемых в серверо-центрической модели, клиенто-центрическиестраницы содержат код JavaScript, который управляет удаленными операциями(такими, как сетевые вызовы и привязка данных). В типичной для Atlas ситуа-ции клиент передает серию внеполосных вызовов для обмена данными с серве-ром. Возвращаемые блоки данных затем используются для обновления частейпользовательского интерфейса.

Браузер

Представление(HTML/CSS)

IПосредники!для обращения

ужбам JAtlas - "^

I кслу

Поведениепользовательского

интерфейса(сценарный код)

Приложение ASP.NET

Исходное построение

(пользовательскийинтерфейс +

сценарный код)

Страницы

Данные

Данные

Сценарная среда Atlas

Средакомпонентов/

пользовательскогоинтерфейса,элементыуправления

Клиентскиеприкладныеслужбы

ASP.NET

Страничнаясреда,

серверныеэлементы

Прикладныеслужбы

Рис. 2.4. Клиенто-центрическая программная модель Atlas

Принципиальное отличие между серверо-центрическими и клиенто-центри-ческими страницами заключается в отношении к коду JavaScript и его использо-ванию. Очевидно, JavaScript — единственное средство управления операциями,доступное в большинстве распространенных браузеров. Клиентская библиотекаAtlas дополнительно обогащает арсенал JavaScript расширенной системой типоввремени выполнения и иерархией классов.

Сценарные аспекты поведенияРасширители, работающие на стороне сервера, определяют аспекты поведения,которые могут присоединяться к различным элементам ASP.NET. Два самыхраспространенных примера — перетаскивание и автозаполнение. Расширительпредставляет собой компонент, который работает на стороне клиента, но может

Page 58: Microsoft ASP.NET 2.0 AJAX

5 8 Глава 2. Структурные элементы Atlas

связываться с целевым элементом на сервере. Расширяемый элемент ASP.NETсвязывается с клиентским сценарием, обеспечивающим требуемое расширенноеповедение.

Расширенное поведение инициируется клиентскими событиями, в том числеперемещениями мыши, нажатиями клавиш и срабатыванием таймеров. Аспектыповедения реализуются блоками сценарного кода, которые могут обновлять свой-ства, вызывать методы и предоставлять относительно сложную функциональ-ность (такую, как автозаполнение). С одним элементом можно связать несколь-ко аспектов поведения, причем это можно сделать как со стороны сервера припомощи расширителей, так и со стороны клиента при помощи сценариев.

В Atlas включено несколько заранее определенных аспектов поведения, в томчисле AutoComplete, Click, Hover и Pop-up windows. AutoComplete расширяетклиентский элемент TextBox и вовремя отображает раскрывающийся список с пред-полагаемыми строками. Click позволяет программировать на JavaScript дейст-вия, выполняемые при щелчке на элементе HTML. Hover активизируется тогда,когда указатель мыши задерживается над элементом разметки. Наконец, Pop-upwindows преобразует блок разметки в «плавающий» элемент, который можетперемещаться по странице.

Подключение к внешним службамКлиентские страницы с поддержкой Atlas могут легко подключаться к веб-служ-бам для получения и отправки данных. Прикладная среда Atlas автоматическизагружает метаданные веб-службы и генерирует JavaScript-посредника, вызываю-щего методы службы с использованием объекта XmlHttpRequest. Такие посред-ники полностью избавляют разработчика от необходимости напрямую работатьс протоколом SOAP (Simple Object Access Protocol) или языком WSDL (WebServices Description Language).

Веб-службы, предназначенные для вызова из Atlas, пишутся с использовани-ем либо WCF (Windows Communication Foundation), либо классической плат-формы ASP.NET. В обоих случаях Atlas работает со службами одинаково. Одна-ко страницы с поддержкой Atlas ограничиваются обращением только к службам,находящимся на их домашнем веб-сервере. А если потребуется написать страни-цу, обращающуюся к внешней веб-службе?

Atlas включает технологию создания мостов, позволяющую создавать локаль-ные шлюзы к удаленным веб-службам. При этом браузер взаимодействует ис-ключительно с кодом моста, находящемся на домашнем сервере. В свою очередь,мост взаимодействует с указанной веб-службой (находящейся где угодно в Ин-тернете), пересылает и принимает данные для клиентского приложения.

Atlas XML ScriptВследствие своей архитектуры Atlas охватывает как клиентскую, так и сервер-ную разработку, а также устанавливает собственные механизмы на каналах связи,существующих между клиентом и сервером. Как следствие, компоненты, нахо-дящиеся на стороне клиента, принципиально отличаются от компонентов, на-ходящихся на стороне сервера.

Page 59: Microsoft ASP.NET 2.0 AJAX

Программная модель Atlas 5 9

С точки зрения программирования клиент относится к «миру JavaScript»,тогда как на сервере правят управляемые языки вроде C# и Visual Basic .NET(если ограничиться серверной средой ASP.NET).

Как и обычные элементы ASP.NET, серверные элементы Atlas выдают кли-ентскую разметку HTML и сценарный код. Разметка в сочетании со сценарнымкодом формирует своего рода клиентскую программируемую версию серверногоэлемента. Различия между обычными элементами ASP.NET и элементами Atlasзаключаются в модели программирования, предоставляемой клиентской сторо-не. Традиционные элементы ASP.NET практически не предоставляют никакоймодели программирования; в Atlas такая модель обладает богатыми возможностя-ми. Кроме того, для обеспечения совместимости браузеров клиентская разметкадолжна представлять собой «чистый» код HTML с элементами, интерпретируе-мыми парсерами HTML всех основных браузеров. Разметка HTML должна бытьдостаточно полной для передачи всей информации, необходимой runtime-средеAtlas для создания подходящей модели программирования для клиентских эле-ментов, но не слишком сложной для правильного воспроизведения в любом кон-кретном браузере.

Для связывания элементов HTML со сценарным кодом и формирования вир-туальных элементов на стороне клиента, а также для того, чтобы оградить разра-ботчика от различий в программных моделях браузеров, в Atlas появился новыйдекларативный язык разметки, называемый XML Script.

Цели и преимущества XML ScriptДля настройки конфигурации элементов на стороне клиента, а также связываниязадач с событиями обычно применяется язык JavaScript. В дополнение к импе-ративному подходу, обеспечиваемому языком программирования, Atlas такжепредлагает другой, декларативный подход, основанный на языке XML Script.

Используя XML Script, можно на декларативном уровне определить аспектыповедения, ожидаемые от элементов клиентской страницы, и связать их междусобой или поступающими данными. В XML Script вы создаете уровень деклара-тивного кода, который на основании существующих тегов HTML и предостав-ленной информации привязки расширяет модель DOM страницы для созданиясети программируемых компонентов, логически сходных с серверными элемен-тами ASP.NET.

Основной идеей при создании Atlas XML Script была возможность определе-ния поведения страниц Atlas на отдельном уровне. В этом случае каждую стра-ницу можно представить как состоящую из трех уровней: содержимого, стиляи поведения. Разумеется, уровень поведения клиентской страницы может бытьвыражен посредством кода JavaScript, но декларативный подход имеет свои преи-мущества.I Генерировать разметку с использованием серверных элементов проще, чемс использованием кода JavaScript. Кроме того, декларативная разметка из-начально проще конструируется, что может упростить будущую разработкуспециализированных функций в Visual Studio.

Page 60: Microsoft ASP.NET 2.0 AJAX

6 0 Глава 2. Структурные элементы Atlas

I При декларативном подходе вы указываете, что будут делать элементы стра-ницы, но не как они должны это делать. Затем происходит разбор разметки,и в конечном итоге генерируется код JavaScript, однако все это делается неза-метно для разработчика.

I Читатели, обладающие опытом работы с Dynamic HTML и Dynamic HTMLBehaviors в Internet Explorer 5.0 и 5.5, знают, каким сложным и длинным частостановится код даже для относительно простых сценариев. Управление несколь-кими элементами страницы через сценарный код кажется простой и быстройзадачей; управление всеми элементами современной широкофункциональнойвеб-страницы является делом сложным и чреватым ошибками. Несомненно,средства автоматизации справятся с этой задачей лучше и быстрее.К XML Script не стоит относиться как к новому языку, который вам как раз-

работчику Atlas обязательно придется изучать. XML Script скорее является ча-стью модели программирования Atlas и во многих ситуациях остается невиди-мым для разработчиков. Серверные элементы Atlas проектировались так, чтобыполностью оградить разработчика от тонкостей этой модели. Для целей разра-ботки вы продолжаете использовать знакомые серверные элементы. Тем не ме-нее «за кулисами» элементы Atlas генерируют XML Script для описания ожидае-мого поведения своих аналогов на стороне клиента.

ПРИМЕЧАНИЕXML Script не всегда избавляет от необходимости во встроенном коде JavaScript. Прижелании разработчики могут внедрять его вручную в клиентские страницы.

Синтаксис Atlas XML Script базируется на XML. Отправной точкой для егосоздания стала необходимость вставки в страницу специализированной размет-ки без нарушения нормальной работы парсера HTML и без ущерба для областиприменения приложений. Скажем, нестандартные теги для этой цели попростуне подходят. В итоге было принято решение использовать тег <script> со специа-лизированным атрибутом типа, встроенный в страницу. Из-за нестандартногоатрибута типа («text/xml-script») браузерный парсер HTML полностью игнори-рует весь тег. Внутри тега содержимое выражается в синтаксисе XML и обраба-тывается на стороне клиента менеджером сценариев Atlas.

XML Script в действииЧтобы поближе познакомиться с синтаксисом и семантикой XML, рассмотримконкретный пример. Представьте страницу ASP.NET с поддержкой Atlas, содер-жащую элементы TextBox и Label. Мы хотим, чтобы текст Label синхронизиро-вался с содержимым TextBox после редактирования текста. И конечно, это долж-но быть сделано без применения традиционных возвратов данных (postbacks).Страница ASP.NET будет содержать два обычных серверных элемента. Обратитевнимание: чтобы код XML Script работал, страница также должна включать эле-мент ScriptManager, как показано в следующем фрагменте:

<atlas:ScriptManager ID="scriptManagerl" runat="server" /><asp:textbox runat="server" id="TextBoxl" />

Page 61: Microsoft ASP.NET 2.0 AJAX

Программная модель Atlas 6 1

<br /><asp:label runat="server" id="Label1" />

Разметка страницы, передаваемая браузеру, содержат следующий фрагмент:<input name="TextBoxl" type="text" id="TextBoxl" /><br /><span id="Labell"></span>

Для реализации желаемого поведения в страницу включается встроенная раз-метка XML Script:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><textBox id="TextBoxl" /><label id="Labell">

<bindings><binding dataContext="TextBoxl"

dataPath="Text"property="Text" />

</bindings></label>

</components></page></script>

Тег <textBox> приказывает клиентской инфраструктуре Atlas преобразовать эле-мент HTML TextBoxl в клиентский элемент Atlas TextBox. Каждый тег <textBox>представляется клиентским элементом Web.Ul.TextBox, определяемым в MicrosoftAJAX Library. Аналогичный элемент <label> обновляет указанную разметку HTML(LabeM в данном примере) до экземпляра клиентского элемента Web.Ul.Label(клиентские элементы рассматриваются в главе 5).

Клиентские элементы Atlas имеют ряд привязок. В частности, свойство Textэлемента Label (атрибут property) связывается со свойством Text (атрибут dataPath)элемента TextBoxl. В результате, как только пользователь нажимает клавишу Tab,чтобы покинуть клиентский элемент TextBox, содержимое свойства Text синхрони-зируется со свойством Text элемента Label. На стороне клиента элемент TextBoxпредставлен объектом JavaScript, свойство Text которого инкапсулирует значе-ние нижележащего текстового поля. Аналогично, клиентский элемент Label ото-бражается на объект JavaScript, а свойство Text связывается с внутренним тек-стом тега <span>.

Класс JavaScript Component является базовым для компонентов — таких, какэлементы управления и аспекты поведения. Класс реализует систему оповеще-ния об изменениях свойств, посредством которой элементы получают информа-цию об изменении свойств других элементов. Клиентский элемент Atlas TextBoxделает это для свойства Text. Система оповещений Atlas срабатывает при вызовеметода записи свойства Text или при инициировании события onchange. В ре-зультате Atlas получает возможность обновить все привязки, в которых задейст-вовано свойство Text элемента TextBox.

Page 62: Microsoft ASP.NET 2.0 AJAX

6 2 Глава 2. Структурные элементы Atlas

Компонент ScriptManagerЛюбая страница Atlas может содержать ровно один экземпляр менеджера сцена-риев — серверного элемента ScriptManager. Элемент ScriptManager, определяемыйв пространстве имен Microsoft.Web.UI, организует работу большей части сервер-ной инфраструктуры Atlas, а также управляет многими аспектами клиентскойфункциональности.

В частности, элемент ScriptManager отвечает за выдачу кода XML Script дляобращения к внешним веб-службам и расширения элементов. Также на элементScriptManager возлагается задача частичного обновления клиентских страниц черезэлемент UpdatePanel (эта тема более подробно рассматривается в следующей главе).

Программный интерфейсВ табл. 2.1 перечислены открытые свойства, определенные для элемента Script-Manager. Все они могут задаваться как на стадии конструирования, так и на про-граммном уровне при инициализации страницы Atlas.

Таблица 2.1. Свойства элемента ScriptManager

Свойство ОписаниеEnablePartialRendering Свойство указывает, поддерживает ли элемент частичное

обновление страниц с использованием элементаUpdatePanel — см. главу 3 (по умолчанию false)

EnableScriptComponents Свойство указывает, какой набор runtime-возможностейдолжен быть включен в клиентскую страницу в видезаранее определенных файлов JavaScript. Если свойстворавно true, в страницу включается ссылка на файл atlas.js,а при значении false — ссылка на файл atlasruntime.js,содержащий облегченный, минимальный набор функций(по умолчанию true)

EnableScriptGlobalization Свойство указывает, должен ли менеджер сценариеввключить в страницу обработчик atlasglob.axd. Этотобработчик генерирует в страницу объект CultureJavaScript, который используется некоторыми методамиклассов Atlas Class Library, зависимыми от локальногоконтекста (по умолчанию true)

ErrorTemplate Свойство определяет шаблон уровня страницы,используемый в случае возникновения ошибок привыполнении асинхронной операции

IsInPartialRenderingMode Свойство доступно только для чтения; указывает,поддерживает ли элемент в настоящее время частичноеобновление с использованием элемента UpdatePanel —см. главу 3 (по умолчанию false)

Scripts Свойство возвращает коллекцию объектов ScriptReference;каждый объект представляет сценарный файл, ссылкана который присутствует в странице

Page 63: Microsoft ASP.NET 2.0 AJAX

Компонент ScriptManager 6 3

Свойство ОписаниеServices Свойство возвращает коллекцию объектов ServiceReference;

каждый объект представляет веб-службу, ссылка накоторую присутствует в странице

В табл. 2.2 перечислены методы элемента ScriptManager.

Таблица 2.2. Методы элемента ScriptManager

Метод ОписаниеRegisterAsyncPostbackControl Метод регистрирует серверный элемент, который

может использоваться со стороны клиента дляобновления панели

RegisterControl Метод регистрирует элемент с включенной поддержкойAtlas; регистрация необходима для управленияэлементом со стороны механизма XML Script

RegisterScriptNamespace Метод регистрирует пространство имен XML дляразметки XML Script

RegisterScriptReference Метод регистрирует URL сценарного файла,включаемого в коллекцию Scripts

RegisterScriptService Метод регистрирует URL веб-службы, включаемойв коллекцию Scripts

RegisterUpdatePanel Метод регистрирует элемент UpdatePanel для текущейстраницы

Элемент ScriptManager также инициирует событие с именем PageError. Со-бытие инициируется при любых ошибках, происходящих в странице в процессечастичного обновления. Обработчик события имеет следующую форму:

public delegate void PageErrorEventHandler(object sender, PageErrorEventArgs e);

Структура данных события расширяет базовый класс EventArgs двумя допол-нительными полями:

public class PageErrorEventArgs : EventArgs{

public PageErrorEventArgs(Exception error);public Exception Error { get; }public string ErrorMessage { get; set; }

}

Наконец, элемент ScriptManager содержит статический метод с именем Get-Current, который обычно используется элементами для получения текущего ме-неджера сценариев страницы.

Элемент ScriptManager управляет многими операциями в контексте страницыAtlas. Давайте в общих чертах обсудим самые важные из них.

Page 64: Microsoft ASP.NET 2.0 AJAX

6 4 Глава 2. Структурные элементы Atlas

Настройка конфигурации страниц AtlasКак упоминалось ранее, элемент ScriptManager является «нервным узлом» стра-ницы Atlas. Для работы страницы Atlas необходим большой объем сценарногокода клиентской стороны, который обеспечивает работу с клиентской библиоте-кой Atlas через API, соответствующий возможностям текущего браузера.

Менеджер сценариев определяет, какие из стандартных файлов необходимоподключить, и решает эту задачу в зависимости от значения свойства Enable-ScriptComponents и версии приложения (отладочной или окончательной).

Не все страницы Atlas требуют одинакового набора клиентских возможно-стей, но ни одна страница не обойдется без минимального объема кода JavaScript.Если для конкретной страницы нужна облегченная версия Atlas, свойство Enable-ScriptComponents задается равным false. В этом случае менеджер сценариев вклю-чает ссылку на файл AtlasRuntime.js вместо файла Atlas.js (за дополнительной ин-формацией о клиентских файлах Atlas обращайтесь к табл. 2.3). Облегченнаяruntime-среда Atlas включает модель ООП JavaScript, а также возможность вы-зова веб-служб и методов страницы.

Элемент SciptManager просматривает данные конфигурации в файле web.configи определяет, нужна ли отладочная информация для текущей версии приложе-ния. В этом случае включаются отладочные версии необходимых сценариев Atlas.

ПРИМЕЧАНИЕКлиентская библиотека Atlas предоставляет высокоуровневый API, маскирующийразличия между реализациями DOM и JavaScript разных браузеров. Этот уровень кодачасто называется прослойкой совместимости.

Обработка исключений в страницах AtlasЭлемент ScriptManager может перехватывать любые исключения, возникающиепри частичном обновлении страницы (то есть при использовании в страницеэлемента UpdatePanel), и выводить шаблон, назначенный пользователем, — этотшаблон задается содержимым свойства ErrorTemplate:

<atlas:ScriptManager ID="scriptManager" runat="server"EnablePartialRendering="true">

<ErrorTemplate>An error occurred

</ErrorTemplate></atlas:ScriptManager>

Если для страницы задан шаблон ошибки, в нее включается скрытая таблицаHTML. Когда в процессе частичного обновления происходит исключение, клиент-ская инфраструктура Atlas делает таблицу видимой и блокирует все поля страницы.

Добавление внешних ссылокСтраница Atlas может содержать ссылки на файлы JavaScript и веб-службы — как веб-службы ASP.NET, так и службы WCF. Подключение необходимых службможет осуществляться на программном уровне при помощи соответствующих

Page 65: Microsoft ASP.NET 2.0 AJAX

Компонент ScriptManager 6 5

методов регистрации (табл. 2.3). Кроме того, ссылки можно добавить вручнуюв коллекции Scripts и Services.

Наконец, статические ссылки на сценарии и веб-службы можно определитьна стадии конструирования при помощи тегов ASP.NET:

<atlas:ScriptManager ID="scriptManagerl" runat="server"><Services>

<atlas:ServiceReference Path="YourService.asmx" /></Services>

</atlas:ScriptManager>

Класс ServiceReference содержит три свойства:public class ServiceReference{

public bool GenerateProxy { get; set; }public string Path { get; set; }public string Type { get; set; }

}

Свойство GenerateProxy (по умолчанию true) указывает, должен ли компонентScriptManager создать класс-посредника JavaScript для подключаемой веб-служ-бы. Свойство Path определяет URL веб-службы ASP.NET (находящейся на од-ном сервере с приложением). Свойство Туре задает тип службы для служб WCF.

Пример включения сценарных файлов в страницу Atlas:<atlas:ScriptManager runat="server" id="scriptManager">

<Scripts><atlas:ScriptReference ScriptName="AtlasllIGlitz" /><atlas:ScriptReference Path=" MyControls.js" Browser="Firefox" /><atlas:ScriptReference Path="MyControls.js" />

</Scripts></atlas:ScriptManager>

Класс ScriptReference содержит три свойства, как видно из следующего опре-деления класса:

public class ScriptReference{

public string Browser { get; set; }public string Path { get; set; }public FrameworkScript ScriptName { get; set; }

}

Свойство ScriptName используется для связывания со стандартными кли-ентскими файлами Atlas. Список таких файлов приводится в табл. 2.3 позднеев этой главе. Учтите, что из всех стандартных файлов обязательным для каждойстраницы является только файл Atlas.js или AtlasRuntime.js. Все остальные файлыне обязательны и подключаются в случае необходимости. Для идентификациистандартных клиентских файлов используется не путь и не имя, а заранее опре-деленные символические константы перечисляемого типа FrameworkScript.

Для нестандартных сценарных файлов атрибут Path обозначает URL, а атри-бут Browser — браузер, для которого предназначен данный файл.

Page 66: Microsoft ASP.NET 2.0 AJAX

6 6 Глава 2. Структурные элементы Atlas

ПРИМЕЧАНИЕКомпонент ScriptManagerProxy тесно связан с элементом ScriptManager. Если основ-ная страница содержит элемент ScriptManager, ни одна из страниц содержимого нипри каких условиях не может содержать второй экземпляр ScriptManager. Тем неменее в некоторых ситуациях может возникнуть необходимость в явной ссылке наScriptManager для включения сценария Atlas в страницу содержимого. В таких слу-чаях вместо ScriptManager используется компонент ScriptManagerProxy (с таким жесинтаксисом, как и для ScriptManager):<asp:Content ...>

<atlas:ScriptManagerProxy runat="server" id="proxy">

</atlas:ScriptManagerProxy></asp:Content>

Пример страницы AtlasИтак, прикладная среда Atlas позволяет создавать широкофункциональные кли-ентские приложения, которые после исходного построения работают на сервереи передают результаты клиенту. Затем клиентский интерфейс обновляется в соот-ветствии с изменениями в данных. Обновление элементов для отражения изме-ненных данных на построенной странице требует использования языка JavaScript.Несмотря на свое сходство с некоторыми языками семейства C, JavaScript непользуется популярностью у многих разработчиков. По этой причине Atlasпредлагает разработчику две модели программирования: серверо-центрическуюи клиенто-центрическую. Результаты, полученные при использовании двух мо-делей, почти не отличаются; однако серверо-центрическая модель позволяет на-делить страницы поддержкой Atlas практически без написания кода JavaScript.

К этому моменту вы уже достаточно хорошо понимаете, что собой представля-ет прикладная среда Atlas и как она работает. Пора переходить от теории к прак-тике — давайте построим и протестируем свои первые страницы Atlas. Для на-чала я выбрал пару несложных примеров, которые дают хорошее представлениео стиле AJAX.

ПРИМЕЧАНИЕВ примерах будет использоваться код JavaScript; таким образом, оба примера относят-ся к клиенто-центрической модели разработки. И все же прежде всего постарайтесь ра-зобраться в реализуемых функциях, вместо того чтобы обдумывать и оценивать объемиспользуемого кода JavaScript. Созданные нами страницы представляют настоящийпрорыв в веб-программировании и позволяют оценить преимущества Atlas. Мы такжевернемся к этим примерам позднее, при более подробном обсуждении некоторых со-путствующих аспектов.

Конфигурация приложенияПриложение Atlas, прежде всего, является приложением ASP.NET с рядом до-полнительных требований к конфигурации. Аналогично, страницы с поддержкойAtlas представляют собой классические страницы ASP.NET с дополнительной

Page 67: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 6 7

разметкой и кодом JavaScript. Дополнительная разметка и сценарный код боль-шей частью генерируются серверными компонентами. Затем структурные мо-дули Atlas находятся под управлением runtime-модулей, расширяющих кон-вейер ASP.NET.

Изменения в проектеК проектам Atlas предъявляется одно ключевое требование: runtime-сборка Atlasдолжна находиться в папке Bin. Сборке присваивается имя Microsoft.Web.Atlas.Сборка включает в качестве ресурсов ряд файлов JavaScript, формирующих кли-ентскую библиотеку Atlas. Имена этих файлов с краткими описаниями перечис-лены в табл. 2.3.

Таблица 2.3. Исходные файлы JavaScript в приложениях Atlas

Исходный файл ОписаниеAtlas.js

AtlasRuntime.js

AtlasUIDragDrop.js

AtlasUIGlitz.js

AtlasUIMap.js

AtlasCompat.js,AtlasCompat2.js

Полный набор функций Atlas, включая runtime-среду Atlas,клиентские компоненты и элементы управления, а такжеинфраструктура декларативного синтаксиса Atlas,применяемого для определения привязки данных и деталейклиентского пользовательского интерфейса. Файл Atlas.jsвключается по умолчанию при добавлении компонентаScriptManagerМинимальный набор функций Atlas — веб-службы, сетевыеслужбы и основные объектно-ориентированные расширенияJavaScript. Файл используется для ускорения загрузкисценария и в тех случаях, когда другие возможностиAtlas не нужныСодержит сценарий для реализации перетаскивания дляклиентских элементов ASP.NETСодержит сценарий для реализации специальных визуальныхэффектов — таких, как растворение, прозрачность и анимацияНеобязательный файл; реализует функцию виртуальногоотображения, используемую в примере приложенияMicrosoft Virtual EarthДва файла содержат прослойки совместимости сценариев,необходимые для кросс-браузерной работы Atlas

Вам как разработчику страниц не нужно много знать об этих файлах, их содер-жимом и задачах. Элемент ScriptManager сделает все необходимое и подключитнужные файлы в зависимости от функций Atlas, активизированных для каждойконкретной страницы.

Изменения в файле web.configПриложениям с поддержкой Atlas обычно требуется специально настроенный файлweb.config. Если проект Atlas создается с использованием шаблона Visual Stu-dio 2005 (см. рис. 2.1), подходящий конфигурационный файл будет сгенерирован

Page 68: Microsoft ASP.NET 2.0 AJAX

6 8 Глава 2. Структурные элементы Atlas

автоматически. В противном случае вы должны проследить за тем, чтобы в фай-ле web.config присутствовала по крайней мере следующая информация:I настроенная группа Microsoft.Web с секцией Converters;I объявление префикса atlas для серверных элементов, определенных в про-странствах имен Microsoft.Web.UI и Microsoft.Web.Ul.Controls;

I модуль HTTP с именем ScriptModule для перехвата каждого запроса, обращен-ного к открытому методу страницы;

I обработчик HTTP, переназначающий расширение ASMX для обработки за-просов, выдаваемых классами-посредниками JavaScript.Рассмотрим каждый из пунктов более подробно.Следующий сценарий конфигурации определяет новую группу секций с име-

нем Microsoft.Web. Как видно из приведенного фрагмента, в этой группе разре-шается создание дочерней секции с именем Converters.

<configSections><sectionGroup name="microsoft.web"

type="Microsoft.Web.Configuration.MicrosoftWebSectionGroup"><section name="converters"

type="Microsoft.Web.Configuration.ConvertersSection" /></sectionGroup>

</configSections>

В секции Converters перечисляются все стандартные конвертеры JSON, под-держиваемые в Atlas. Список можно расширить и добавить в него узкоспециали-зированные конвертеры для ваших типов данных:

<microsoft.web><converters>

<add type="Microsoft.Web.Script.Serialization.Converters.DataSetConverter" />

<add type="Microsoft.Web.Script.Serialization.Converters.DataRowConverter" />

<add type="Microsoft.Web.Script.Serialization.Converters.DataTableConverter" />

</converters></microsoft.web>

Конвертер Atlas JSON представляет собой класс, производный от абстрактногобазового класса с именем JavaScriptConverter. По умолчанию специализирован-ные конвертеры определяются для нескольких объектов ADO.NET — DataSet,DataTable и DataRow.

Вообще говоря, вам не обязательно создавать конвертер JSON для каждоготипа, связанного с внеполосными вызовами. Atlas автоматически сериализуети десериализует многие управляемые типы в классы JavaScript и обратно. В ча-стности, примитивные типы и нестандартные классы автоматически обрабатыва-ются с применением рефлексии.

В большинстве случаев сериализация нестандартных объектов обходится безнаписания нестандартного конвертера JSON. Впрочем, вы можете написать не-стандартный конвертер JSON, если потребуется взять процесс сериализации под

Page 69: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 6 9

полный контроль. Обычно нестандартный конвертер создается тогда, когда объ-ект слишком сложен для представления в формате класса JavaScript, а сериа-лизатор JSON может сделать неверные предположения по поводу корректногоспособа сериализации. Если вы хотите быть полностью уверены в том, что ваш(сложный) объект сериализуется верно, а встроенный сериализатор JSON вы-дает ошибки, по крайней мере, у вас имеется запасной вариант с построениемнестандартного конвертера.

Если в приложении используются серверные элементы Atlas (которые бу-дут рассматриваться, начиная с главы 3), также необходимо зарегистрироватьпрефикс atlas, который будет использоваться вместо стандартного префикса aspв качестве отличительного признака элементов:

<pages><controls>

<add namespace="Microsoft.Web. Ш "assembly="Microsoft.Web.Atlas"tagPrefix="atlas" />

<add namespace="Microsoft.Web.Ill.Controls"assembly="Microsoft.Web.Atlas"tagPrefix="atlas" />

</controls></pages>

Префикс тега atlas ассоциируется с элементами, определяемыми в сборке Micro-soft.Web.Atlas, и конкретно в пространствах имен Microsoft.Web.UI и Microsoft.Web.Ul.Controls.

Изменения в конвейере ASP.NETРабота страницы Atlas в основном состоит из отправки внеполосных вызововсерверу и последующего обновления объектной модели документа страницы по-лученными данными. В некоторых случаях для успешной обработки внеполос-ных вызовов, инициируемых клиентом, требуется внести небольшие измененияв конвейер ASP.NET.

В частности, когда клиентская страница обращается с вызовом к веб-службе,потребуется специализированный обработчик HTTP для ресурса .asmx. Новыйобработчик должен различать традиционные обращения к веб-службам (черезбраузер или классы-посредники .NET) и вызовы через классы-посредники Java-Script. В последнем случае обработчик должен гарантировать, что объект JavaScriptсодержит возвращаемое значение метода. Для обработки всех ресурсов .asmx вме-сто исходного обработчика ASP.NET регистрируется новый объект ScriptHandler-Factory, как показано в следующем фрагменте:

<httpHandlers><remove verb="*" path="*.asmx"/><add verb="*" path="*.asmx"

type="Microsoft.Web.Services.ScriptHandlerFactory" /></httpHandlers>

Обращения к веб-службам, проходящие через посредников JavaScript, можноотличить по суффиксу /js в URL.

Page 70: Microsoft ASP.NET 2.0 AJAX

7 0 Глава 2. Структурные элементы Atlas

ScriptHandlerFactory проверяет суффикс (если он есть) и использует обработ-чик Atlas HTTP или традиционный обработчик веб-служб ASP.NET, в зависи-мости от результата.

Другая распространенная разновидность внеполосных вызовов обращена к ме-тодам страниц. В этом случае код JavaScript, встроенный в страницу HTML, об-ращается с вызовом к той же странице .aspx и требует выполнить конкретныйметод. Для удовлетворения подобных запросов необходимо внести некоторыеизменения в стандартный жизненный цикл страницы.

<httpModules><add name="ScriptModule"

type="Microsoft.Web.Services.ScriptModule" /></httpModules>

Учтите, что сценарный модуль HTTP не понадобится, если ваше приложениене собирается вызывать методы страниц из своих страниц ASP.NET. Аналогич-но, вам не придется заменять обработчик HTTP для ресурсов .asmx, если ни однастраница не обращается с вызовами к веб-службам.

Удаленный вызов методовНаше знакомство с программной моделью Atlas начнется с рассмотрения двухстраниц, реализующих внеполосные вызовы — несомненно, самая типичная опе-рация, характерная для AJAX-ориентированных решений. Сначала мы разберем-ся, как использовать Atlas для вызова веб-службы со стороны клиента, а затемя покажу, как построить страницу Atlas с вызовом метода страницы.

Обращение к веб-службеКаждая страница с включенной поддержкой Atlas должна содержать элементScriptManager. Кроме того, если страница вызывает веб-службы, менеджер сце-нариев должен быть явно связан с каждой вызываемой службой, как показанов следующем фрагменте:

<atlas:ScriptManager ID="scriptManagerl" runat="server"><Services>

<atlas:ServiceReference Path="~/WebServices/MyDataService.asmx" /></Services>

</atlas:ScriptManager>

Для каждой веб-службы, которая может вызываться страницей, создается узелServiceReference. Ссылка создается статически на стадии конструирования илидинамически, посредством добавления объекта ServiceReference в коллекциюServices менеджера сценариев. Вот как это делается:

ServiceReference service = new ServiceReference();serviее.Path = "-/WebServices/MyDataService.asmx";service.GenerateProxy = true;scriptManagerl.Services.Add(service);

Лучшим местом для размещения этого кода является событие Page_Loadстраницы.

Page 71: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 7 1

Инфраструктура Atlas генерирует клиентский объект-посредника JavaScriptдля каждой веб-службы, для которой создается ссылка. В результате появляетсявозможность включить в клиентскую страницу сценарный код, который вызыва-ет методы веб-службы через класс JavaScript. Допустим, на странице находитсяраскрывающийся список для выбора имени клиента и кнопка.

<body><form id="forml" runat="server"><atlas:ScriptManager ID="scriptManagerl" runat="server">

<Services><atlas:ServiceReference Path="~/WebServices/MyDataService.asmx" />

</Services></atlas:ScriptManager>

<asp:DropDownList ID="CustomerList" runat="server"DataSourceID="CustomerDataSource"DataTextField="CompanyName"DataValueField="ID" />

<asp:ObjectDataSource ID="CustomerDataSource" runat="server"TypeName="IntroAtlas.CustomerManager"SelectMethod="LoadAll">

</asp:ObjectDataSource>

<input type="button" value="Find customer" onclick="findCustomer()" /><hr /><div id="CustomerData" style="visibi1ity:hidden"><table><tr>

<td class="label">ID</td><td style="width:10px;" /><td><span id="companyID"></span></td>

</tr><tr><td class="label">Company</td><td style="width:10px;" /><td><span id="companyNanie"></span></td>

</tr><tr><td class="label">Contact</td><td style="width:10px;" /><td><span id="companyContact"></span></td>

</tr><tr><td class="label">City</td><td style="width:10px;" /><td><span id="companyCity"></span></td>

</tr><tr><td class="label">Country</td><td style="width:10px;" /><td><span id="companyCountry"></span></td>

</tr></table></div></form>

</body>

Список заполняется с использованием элемента источника данных, связанно-го с объектом DAL (Data Access Layer). Выбрав клиента в списке, пользователь

Page 72: Microsoft ASP.NET 2.0 AJAX

7 2 Глава 2. Структурные элементы Atlas

щелкает на кнопке, после чего выполняется код JavaScript. Чтобы щелчок неинициировал полную передачу данных, следует использовать либо обычнуюкнопку HTML, как в данном примере, либо кнопку ASP.NET со свойством Оп-ClientClick, содержащим код findcustomerQ; return false; (возврат false предотвра-щает операцию отправки):

<asp:Button ID="Button1" runat="server" OnClientClick="findcustomer();return false;" Text="Find customer" />

А вот как выглядит вызываемый код клиентской стороны:function findCustomerO{

// Получение элемента раскрывающегося спискаvar list = document.getElementByldC'CustomerList");

// Получение текущего выделенного значения в спискеvar custID = list.options[list.selectedIndex].value

// Вызов веб-службы через класс-посредникаIntroAtlas.WebServices.MyDataService.LookupCustomer(

custID,onSearchComplete);

}

Типичный код JavaScript для события щелчка на кнопке сначала получает те-кущее выделенное значение в раскрывающемся списке, а затем вызывает методвеб-службы через класс-посредника. Класс-посредник JavaScript обладает темже именем, что и класс веб-службы (IntroAtlas.WebServices.MyDataService в нашемпримере), а количество его методов совпадает с количеством веб-методов исход-ной веб-службы. В рассмотренном примере веб-служба MyDataService.asmx со-держит как минимум веб-метод с именем LookupCustomer. Далее приводится вы-держка из кода веб-службы:

namespace IntroAtlas.WebServices{

[WebService(Namespace = "http://introatlas.book/");[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfilel_l)Ipublic class MyDataService : System.Web.Services.WebService{

public MyDataServiceO{}

[WebMethod;public Customer LookupCustomer(string id){

return CustomerManager.Load(id);}

}

Посредник JavaScript для веб-службы генерируется на сервере инфраструк-турой Atlas и связывается с клиентской страницей в виде сценарного кода.

Page 73: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 7 3

Метод LookupCustomer класса-посредника JavaScript содержит один дополни-тельный аргумент — функцию обратного вызова, которая активизируется припоявлении готовых результатов веб-службы. В нашем примере эта функция об-ратного вызова в следующем примере называется onSearchComplete:

function onSearchComplete(data){

// Возвращаемые данные представляют собой объект JavaScript,// "похожий" на возвращаемое значение вызванного метода веб-службы -// в данном примере это тип Customer.// of the invoked Web service method-in this case, the Customer type.document.getElementById("CustomerData").style.visibility = "visible";document.getElementByldC'companylD").innerText = data.ID;document.getElementById("companyName").innerText = data.CompanyName;document.getElementById("companyContact").innerText = data.ContactName;document.getElementByldC'companyCity").innerText = data.City;document.getElementById("companyCountry").innerText = data.Country;

}

Инфраструктура Atlas JSON гарантирует, что во входном аргументе функцииобратного вызова будет передаваться JavaScript, полученный в результате сериа-лизации возвращаемого значения метода (тип .NET) в объект JavaScript. Коли-чество полей в объекте, представленном формальным параметром data, соответ-ствует количеству открытых свойств в исходном типе Customer, возвращеннымметодом LookupCustomer.

Функция обратного вызова JavaScript использует результаты, полученные отметода веб-службы, для обновления частей текущей страницы через интерфейсDOM. На рис. 2.5 показан пример страницы, которая была по щелчку обновленаданными, полученными от веб-службы.

Рис. 2.5. Пример страницы Atlas, обращающейся с вызовом к веб-службе

Page 74: Microsoft ASP.NET 2.0 AJAX

7 4 Глава 2. Структурные элементы Atlas

ПРИМЕЧАНИЕВероятно, вы заметили, что в этом примере используется локальная веб-служба, нахо-дящаяся на одном сервере и в одном приложении с вызывающей страницей. Данныйфакт не случаен — по соображениям быстродействия Atlas поддерживает прямые вы-зовы веб-служб только в том случае, если они обращены к службам, предоставляемымтем же веб-приложением. Учтите, что речь идет не о техническом ограничении, а о со-знательном архитектурном решении. Как будет показано подробнее в главе 6, Atlas так-же позволяет создавать серверные шлюзы для связывания клиентских страниц с внеш-ними веб-службами. Конечно, обращения к внешним веб-службам из страницы Atlasвозможны, но выполняются они не так, как показано в этой главе.

Вызов метода страницыПомимо вызова веб-служб из клиентской страницы также существует возмож-ность вызова методов той же серверной страницы. Второй подход на логическомуровне близок к ASP.NET 2.0 Script Callback API, кратко описанному в главе 1.

Метод страницы в Atlas представляет собой открытый метод класса программ-ной логики (code-behind class), помеченный конкретным атрибутом WebMethod.Точно такой же атрибут используется для пометки методов веб-служб, предна-значенных для открытого вызова через Web. Иначе говоря, определяя методыстраницы, вы превращаете страницу в некую разновидность веб-службы, доступ-ной для клиентских страниц Atlas.

Чтобы использование атрибута WebMethod стало возможным, необходимо им-портировать в страницу пространство имен System.Web.Services:

<%$ Import Namespace="System.Web.Services" %>

Затем вы конструируете страницу, как считаете нужным, но обязательно раз-мещаете на ней элемент ScriptManager и клиентскую кнопку (или другой клиент-ский элемент разметки HTML, инициирующий событие). Предположим, на фор-ме имеется поле TextBox для ввода кода клиента и кнопка:

<asp:TextBox ID="CustomerID" runat="server" /><input type="button" value="Find customer" onclick="findCustomer()" />

Обработчик JavaScript onclick сходен с обработчиком, созданным нами дляпредыдущего примера, если не считать того, что в нем используется другой по-средник. На этот раз объекту-посреднику присвоено имя PageMethods:

function findCustomerO{

var id = document.getElementByldC'CustomerlD").value;PageMethods.LookupCustomer(id, onSearchComplete);

}

Функция обратного вызова onSearchComplete совпадает с одноименной функ-цией из предыдущего примера. Посредник PageMethods создается инфраструк-турой Atlas на основании содержимого нового сценарного блока:

<script type="text/C#" runat="server">[WebMethod;

Page 75: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 7 5

public Customer LookupCustomer(string id){

return LookupCustomerInternal(id);}

</script>

Atlas разбирает секцию <script> c атрибутом type, равным text/C#, и генерируетсоответствующий объект JavaScript PageMethods. Методы страниц должны опре-деляться как встроенные в соответствующих тегах <script>. Тем не менее, чтобыбольшую часть метода не приходилось оформлять в виде встроенного кода, мож-но просто передать управление защищенному методу, определенному в классепрограммной логики. Учтите, что метод класса программной логики не можетбыть приватным; в противном случае он будет недоступен для динамическогокласса страницы, созданного ASP.NET для обслуживания запроса.

В главе 6 мы вернемся к этим клиенто-центрическим примерам, заглянем«за кулисы» и разберемся, что именно происходит, когда клиентская страни-ца вызывает веб-службу или метод страницы. Мы также вернемся к атрибутуWebMethod и его параметрам (таким, как CacheDuration).

Методы веб-служб и методы страницЧем же методы веб-служб отличаются от методов страниц и существуют ли такиеразличия? И какой из двух механизмов лучше подходит для того, чтобы предо-ставить клиенту доступ к серверной функциональности?

На функциональном уровне эти два механизма эквивалентны, хотя они и ис-пользуют разные модели реализации. В обоих случаях в конечном итоге вызыва-ется блок кода, определяемый на стороне клиента.

Выбирая решение с «простой» веб-службой (то есть файл .asmx или службуWCF), вы получаете службу, которую можно настроить на прием запроса от дру-гих клиентов. Код службы отделен от кода страницы, ее использующей, и однаслужба может принимать запросы от нескольких страниц. К достоинствам этогоспособа относятся гибкость и универсальность.

С другой стороны, набор методов страниц позволяет опубликовать страницув виде веб-службы в контексте приложения. Как видите, перспектива получаетсясовершенно иной. Какой программный аспект должен выйти на первый план?Если страница ASP.NET с поддержкой Atlas, выбирайте методы страниц, а еслипредоставляемая функциональность — предпочтение отдается веб-службе.

Методы страниц быстрее реализуются, но взамен вы получаете краткосроч-ное решение, область применения которого не выходит за рамки страницы. Веб-службы обладают заметно большим потенциалом для повторного использования;вероятно, это единственный вариант, который стоит рассматривать в приложе-ниях уровня предприятия.

Еще раз напоминаю, что веб-службы Atlas находятся на том же серверномкомпьютере и в том же веб-приложении. Как будет показано в главе 6, это объяс-няется тем, что веб-службам Atlas необходим специальный обработчик HTTP,генерирующий посредника JavaScript.

Page 76: Microsoft ASP.NET 2.0 AJAX

7 6 Глава 2. Структурные элементы Atlas

ВНИМАНИЕДля вызова методов страниц необходим модуль HTTP ScriptModule, тогда как при вы-зове веб-служб из ваших страниц без него можно обойтись. С другой стороны, вызовывеб-служб требуют обработчика HTTP для ресурсов .asmx, специфического для Atlas.При простом вызове методов страниц этот обработчик игнорируется.

Отладка приложений AtlasПриложения Atlas отличаются от других веб-приложений в нескольких отноше-ниях. Во-первых, они содержат значительный объем клиентского сценарногокода, который должен отлаживаться наряду с серверным кодом. Во-вторых, брау-зер может выдавать дополнительные (и даже асинхронные) запросы данных,в результате которых некоторые традиционные приемы отладки ASP.NET ста-новятся частично неприменимыми.

Впрочем, для отладки приложения, прежде всего, необходимо включить в дво-ичные файлы отладочную информацию. В файле web.config, генерируемом шаб-лоном проекта Atlas в Visual Studio 2005, средства отладки отключены, поэтомупо умолчанию в компилируемые сборки отладочная информация не включается.Следовательно, первое, что необходимо сделать, — это включить отладочный ре-жим в приложении Atlas, по крайней мере, на стадии разработки:

<system.wet»

compilation debug="true">

</compilation>

</system.wet»

При включенном отладочном режиме Atlas автоматически использует отла-дочную версию клиентских библиотек JavaScript. Отладочные библиотеки со-держат дополнительную диагностическую информацию и проверочные условияи даже предоставляют вспомогательный класс для проведения отладки.

Настройка Internet ExplorerДля пошагового выполнения серверного кода в приложениях Atlas разработчикустанавливает точки прерывания в нужных строках кода и нажимает F5. VisualStudio 2005 не позволяет устанавливать точки прерывания в коде JavaScript, од-нако это не означает, что пошаговое выполнение сценарного кода невозможно.

Прежде всего убедитесь в том, что отладка разрешена в Internet Explorer.В меню Сервис (Tools) выберите команду Свойства обозревателя (Internet Options),перейдите на вкладку Дополнительно (Advanced). Убедитесь в том, что для InternetExplorer разрешена отладка сценариев, а также (при желании) отключите под-робные сообщения об ошибках (рис. 2.6).

При включении подробных сообщений об ошибках Internet Explorer заменяетсообщения сервера внутренними сообщениями, ориентированными на конечно-го пользователя, а не на разработчика. Таким образом, для получения более по-лезной информации подробные сообщения стоит временно отключить.

Page 77: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 77

Рис. 2.6. Настройка отладочных параметров в Internet Explorer

Чтобы выполнить клиентский код приложения Atlas в пошаговом режиме, не-обходимо остановить отладчик сразу же, как только он приступит к выполнениюкода JavaScript страницы. Для этого в сценарный код включается вызов debug.fail:

function findCustomer(){

// Этот вызов останавливает отладчик и дает возможность// выполнить код сценария в пошаговом режимеdebug.fail();

// Содержимое сценарной функции

}

Сценарный объект debug входит в отладочные библиотеки Atlas. Вызов егометода fail останавливает работу отладчика. На этой стадии Visual Studio 2005позволяет выполнить сценарный код в пошаговом режиме (клавиша F11), какпоказано на рис. 2.7.

СОВЕТОкно Script Explorer, показанное на рис. 2.7, доступно при отладке веб-приложенияв Visual Studio 2005. Чтобы вызвать его, выполните команду Debug ► Windows и выбе-рите окно Script Explorer.

Page 78: Microsoft ASP.NET 2.0 AJAX

7 8 Глава 2. Структурные элементы Atlas

Рис. 2.7. Пошаговое выполнение сценарного кода после вызова debug.fail

Объект debugОткуда взялся сценарный объект debug? Этот объект JavaScript определяетсяв отладочной версии файла atlas.js. Экземпляр объекта JavaScript (с настоящимименем Web._Debug) создается и присоединяется к свойству window.debug в моде-ли DOM страницы. Методы объекта debug перечислены в табл. 2.4.

Таблица 2.4. Методы сценарного объекта debug

Метод Описание

assert Проверяет выполнение заданного условия

clearTrace Стирает трассировочный вывод

dump Выводит заданный объект в понятной форме в конце страницы

fail Передает управление отладчику. Метод работает только в браузереInternet Explorer

trace Записывает текстовый аргумент в трассировочный вывод

Метод assert имеет следующий прототип:

assert(condition, message, displayCaller);

Page 79: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 7 9

Если условие condition выполняется, метод просто возвращает управление,а выполнение продолжается со следующей команды. Если условие ложно, методвыводит окно с заданным сообщением. Если параметр displayCaller равен true,метод также выводит информацию о вызывающей стороне.

Метод clearTrace вызывается без аргументов и очищает часть страницы, в ко-торой отображаются трассировочные сообщения Atlas. Говоря точнее, методclearTrace просто скрывает компонент-панель, на котором выводятся все трасси-ровочные сообщения.

Метод dump записывает содержимое заданного объекта в форме, доступнойдля человека, в трассировочную область Atlas в конце страницы. Простейшийвариант синтаксиса выглядит так:

function onSearchComplete(results){

debug.dump(results);

}

Результаты показаны на рис. 2.8.

Рис. 2.8. Отладочная трассировка Atlas

При вызове метода dump могут передаваться еще три параметра:debug.dump(object, паше, recursive, indentationPadding)

Page 80: Microsoft ASP.NET 2.0 AJAX

8 0 Глава 2. Структурные элементы Atlas

Параметр name содержит текст, отображаемый в заголовке дампа объекта. Текстможет содержать разметку HTML. Если параметр recursive равен true (значениепо умолчанию), в общий дамп также включаются рекурсивные дампы вложенныхобъектов. Наконец, параметр indentationPadding определяет текст, который долженвыводиться в начале каждой строки дампа. Если отладчик Visual Studio подключенк Internet Explorer, трассировочные сообщения также отображаются в окне Output.

Метод trace записывает свой текстовый аргумент в трассировочный вывод.Он получает единственный параметр — выводимый текст.

Как упоминалось ранее, метод fail останавливает отладчик, но только для брау-зера Internet Explorer. Что делать, если приложение Atlas тестируется в другомбраузере? Вы не сможете использовать отладчик Visual Studio для пошаговоговыполнения клиентского кода в Firefox или другом браузере на базе Mozilla.Впрочем, отладчик для Firefox, реализованный в виде расширения Firefox, мож-но загрузить по адресу http://www.mozilla.org/projects/venkman.

Трассировка на стороне сервераВ ASP.NET часто применяются серверные трассировочные сообщения, содержа-щие информацию о состоянии объекта или о реальной последовательности воз-никновения некоторых событий. Функция трассировки настолько популярна,что группа разработки Atlas сочла необходимым создать объект debug — своегорода трассировщик для клиентской стороны.

В том, что касается трассировки на стороне сервера, Atlas создает некоторыепроблемы. Страница Atlas изначально выдает весь трассировочный вывод в концестраницы, однако трассировка не обновляется по мере выдачи асинхронных вызо-вов. Трассировочный вывод, дописанный в конце страницы, остается неизменнымнезависимо от фактической реализации асинхронных вызовов (методы страниц,веб-службы или, возможно, серверный элемент UpdatePanel — см. главу 3).

В частности, при использовании элемента UpdatePanel будет обновляться толь-ко часть страницы, представленная элементом. В этом случае для вывода трасси-ровочной информации следует использовать подсистему просмотра трассировки(trace.axd). Trace.axd выводит 10 последних запросов приложения и для каждогоможет предоставить вывод трассировочного механизма. За дополнительной ин-формацией о средствах трассировки в ASP.NET обращайтесь к главе 5 моей кни-ги «Programming Microsoft ASP.NET 2.0: Core Reference» (Microsoft Press, 2005).

Отслеживание трафика HTTPВо время своей работы приложение Atlas выдает серию классических отправокданных и внеполосных запросов. Для целей тестирования может потребоватьсяпросмотреть содержимое пакетов запросов и ответов HTTP. В классической мо-дели ASP.NET такая необходимость возникает редко, и даже в таких случаях оналегко реализуется следующей строкой кода:

void Page_Load(object sender, EventArgs e){

Request.SaveAs(file, true);

}

Page 81: Microsoft ASP.NET 2.0 AJAX

Пример страницы Atlas 8 1

С другой стороны, в Atlas асинхронные вызовы производятся с гораздо большейчастотой, а в теле запроса используется нестандартный синтаксис. В то же времяв случае любых неполадок или сбоев особенно важно проанализировать ответ асин-хронного вызова. Нравится вам это или нет, но для выполнения качественных Atlas-разработок вам придется вооружиться средствами отслеживания трафика HTTP.

Несомненно, одним из лучших кандидатов является утилита Fiddler. За ин-формацией о ее возможностях обращайтесь по адресу http://www.fiddlertool.com/fiddler. Утилита сохраняет весь трафик HTTP, чтобы позднее вы могли проана-лизировать содержимое каждого запроса и ответа. Fiddler поддерживает InternetExplorer и другие браузеры.

Утилита ASP.NET Development Helper, разработанная участником группыAtlas, распространяется бесплатно, но работает только с Internet Explorer. Ее можнозагрузить по адресу http://www.nikhilk.net/Project.WebDevHelper.aspx. Утилита позво-ляет просмотреть информацию о текущей странице ASP.NET (например, состояниеотображения и трассировочную информацию). Кроме того, она позволяет выпол-нять некоторые операции на сервере (такие, как перезапуск приложения илиуправление объектом Cache). Наконец, утилита предоставляет возможность «вжи-вую» просматривать модель HTML DOM, а также отслеживать запросы и ответыдля диагностических сценариев. Большая часть функций программы работает толь-ко в том случае, если приложение работает на локальном хосте. При установкепрограммы ряд операций приходится выполнять вручную, потому что она реали-зована как вспомогательный объект браузера Internet Explorer. Впрочем, ничеготакого, что могло бы напугать отважного веб-разработчика, делать не придется.На рис. 2.9 показано рабочее окно утилиты. После того как утилита будет установ-лена, выполните команду Вид (View) ► (Explorer Bar) и выберите утилиту в меню.

Рис. 2.9. Утилита ASP.NET Development Helper

Page 82: Microsoft ASP.NET 2.0 AJAX

8 2 Глава 2. Структурные элементы Atlas

ЗаключениеТехнология Atlas, проектировавшаяся как составная часть платформы ASP.NET,а не как внешний подключаемый API, имеет две стороны: клиенто-центрическийи серверо-центрический API и программная модель. Главной целью при проектиро-вании Atlas была возможность создания приложений с существенно расширен-ными интерфейсными возможностями. В Web эти возможности обеспечиваютсянемалым объемом кода JavaScript и облегченными вызовами передачи данных.Кто должен писать этот код? Кто должен иметь дело со сценарным языком?

Большинство разработчиков Atlas составляют бывшие разработчики ASP.NET,знакомые с моделью разработки на стороне сервера, основанной на элементах.Серверо-центрическая программная модель Atlas стала следующим шагом в эво-люции модели программирования ASP.NET в процессе ее постепенного смеще-ния к модели AJAX. Серверные элементы Atlas полезны, если вы не настолькоуверены в своих силах, чтобы создавать клиентские сценарии Atlas вручную.

Подлинная сила Atlas проявляется в клиентских сценариях. Возможность ге-нерирования клиентского сценарного кода серверными элементами полезна,но ее гибкость и мощь оставляет желать лучшего. Клиенто-центрическая модельAtlas требует навыков владения JavaScript и DOM, а также хорошего знанияклиентской библиотеки Atlas.

Впрочем, независимо от вашей квалификации и личных предпочтений, одинфакт остается несомненным — для написания хороших приложений AJAX необхо-дима прикладная среда, будь то Atlas или другая разработка сторонней фирмы.

Page 83: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 3 Частичное обновление страницВ этой главе:I Серверные элементы AtlasI Включение частичного обновления страницI Управление обновлением страницI Обратная связь во время обновления

Главной движущей силой за проектом Atlas было желание упростить использо-вание клиентского компьютера (в дополнение к серверной системе) для обработ-ки запроса. В настоящее время работа на стороне клиента требует от разработчи-ков использования языка сценариев, что вовсе не приводит их в восторг. Однивеб-разработчики либо обожают JavaScript (и сценарные языки вообще) и могутдобиться практически любого желаемого результата за счет гибкости синтакси-са, но других выводит из себя один вид клиентского тега <script>.

Несмотря на то что многие прикладные среды на базе AJAX по возможностистараются скрыть технические подробности от разработчика, страница с вклю-ченной поддержкой AJAX как минимум содержит код JavaScript для обновлениячастей страницы, задействованных в удаленных операциях. А по мере того, какразработчик применяет более мощные и сложные функции, ему приходится всечаще иметь дело с JavaScript. Этот принцип остается истинным и для приклад-ной среды Atlas.

Группа разработки Atlas знала об этой проблеме и предложила для ее реше-ния своего рода метаязык — XML Script. Он нивелирует различия в объектныхмоделях документов разных браузеров и гораздо проще генерируется серверны-ми элементами. Разработчик ASP.NET должен достаточно хорошо знать XMLScript, чтобы извлечь максимум пользы из возможностей Atlas. Впрочем, даже необладая такими познаниями, разработчики ASP.NET благодаря серверным эле-ментам Atlas смогут легко пользоваться преимуществами AJAX, затратив мини-мум времени и сил на освоение новой технологии.

Как будет показано в этой главе, для построения эффективных приложенийAtlas вам не придется изучать новую программную модель, сценарный язык илидиалект XML. Тем не менее следует учитывать, что здесь рассматривается лишьнебольшая часть возможностей Atlas, а для полноценного использования плат-формы ASP.NET Atlas вам все равно потребуется хорошее знание XML Script.Язык XML Script подробно рассматривается в главе 5.

Page 84: Microsoft ASP.NET 2.0 AJAX

8 4 Глава 3. Частичное обновление страниц

ПРИМЕЧАНИЕXML Script — метаязык, используемый для описания привязок и аспектов поведе-ния компонентов Atlas. Теги XML Script ссылаются на объекты библиотеки MicrosoftAJAX (см. главу 5). Все, что выражается на XML Script, также может быть выраженокомандами JavaScript. Выбор между XML Script и JavaScript является делом вкуса; длясерверных элементов предпочтение отдается XML Script.

Серверные элементы AtlasСерверные элементы Atlas играют важнейшую роль в сближении модели про-граммирования Atlas с моделью ASP.NET. Если мир AJAX привлекает вас, новам не хочется использовать JavaScript, — для начала подумайте о возможностииспользования этих элементов.

Цели и побудительные мотивыРазработчики могут легко и без лишних затрат наделить функциональностьюAJAX новую или существующую страницу/приложение; ведь для этого необхо-димо лишь добавить новые серверные элементы и настроить их конфигурацию.При использовании серверных элементов Atlas вы идете по пути поэтапной раз-работки и добавляете AJAX-расширения пользовательского интерфейса без по-вторного проектирования кода и структуры страниц.

Избегайте больших объемов кода JavaScriptВ наши дни веб-разработчики делятся на две группы по уровню своей профес-сиональной подготовки: первые хорошо разбираются в сценарном программиро-вании, вторые — нет.

Первая группа состоит из профессионалов, обладающих значительным опы-том работы со страницами HTML, PHP, Perl и, возможно, специализированны-ми инструментариями веб-программирования. Все эти разработчики знакомы сосценарными конструкциями лучше, чем с классами или интерфейсами. Во вто-рую группу входят разработчики, которые начинали свою карьеру с WindowsSDK и принципов ООП, а затем перешли к написанию веб-приложений в про-цессе своей профессиональной эволюции.

Для профессионалов первой группы инициирование удаленного действия,получение результатов и обновление объектной модели документа — вполнепривычное дело. Для второй группы этот процесс может стать сущим кошмаром.Тем не менее обе группы преследуют одну цель — расширение возможностейвеб-приложений. Серверные элементы позволяют разработчикам обеих групп до-биваться этой цели без написания объемистого кода JavaScript.

Впрочем, необходимо учесть одно принципиальное обстоятельство: исполь-зование серверных элементов избавляет от написания больших объемов кодаJavaScript, но не от использования кода JavaScript вообще. Проще говоря, сер-верные элементы генерируют весь необходимый код JavaScript за вас. Задаваясвойства элемента, вы направляете работу элемента, чтобы он сгенерировал сце-нарий с нужной вам функциональностью. Тем не менее код JavaScript все равно

Page 85: Microsoft ASP.NET 2.0 AJAX

Серверные элементы Atlas 8 5

задействован на стороне клиента. Вы отдаете директивы серверному элементу,но не управляете каждым шагом построения сценария и не изменяете сгенери-рованный сценарий. При использовании серверного элемента Atlas вы включае-те в свою страницу компонент, работающий по принципу «черного ящика», и на-чинаете зависеть от его работы.

Держите базовую логику на сервереПри помощи серверных элементов Atlas вы также можете указать, что базовыйинтерфейс пользователя и логика приложения остаются на сервере написанны-ми на полноценном языке вроде Microsoft Visual C# или Microsoft Visual Basic.Большая часть взаимодействий «пользователь/сервер» обрабатывается на серве-ре (как и при классическом возврате данных ASP.NET), а клиенту отправляетсятолько разметка для изменяющихся частей страницы.

Используя серверные элементы, вы можете немедленно приступить к построе-нию страниц Atlas — при условии, что вы уже знаете C# или Visual Basic и зна-комы с основами ASP.NET.

Серверные элементы AtlasСерверные элементы Atlas можно разделить на три категории: обновляемые па-нели, расширители и обертки для компонентов клиентской стороны. В этой гла-ве основное внимание уделяется обновляемым панелям, а расширители и другиеэлементы будут рассматриваться в главе 4.

Обновляемые панелиВ упрощенном изложении модель AJAX позволяет пользователям инициироватьоперации на стороне сервера, получать данные и обновлять текущую страницу.Другими словами, модель AJAX логически делит страницу на обновляемыеобласти. Логика построения нового содержимого находится на сервере (так на-зываемые «операции на стороне сервера») и инициируется в цикле обмена дан-ными. Логика обновления страницы должна быть внедрена в сценарный код,присоединенный к странице.

Серверные элементы Atlas определяют обновляемые области страницы припомощи шаблонов ASP.NET. Когда любой из элементов шаблона инициируетотправку данных, инфраструктура Atlas перехватывает событие и запускает спе-циальный внеполосный вызов. В результате сервер заново генерирует разметкутолько для элементов шаблона и возвращает ее клиенту. Логика обновлениястраницы в этом случае очень проста — она сводится к замене разметки в объ-ектной модели документа страницы.

Ключевое место в этом семействе занимает элемент UpdatePanel — Atlas-версияклассического элемента ASP.NET Panel. Вскоре мы рассмотрим его более подробно.

Расширители и аспекты поведенияКак упоминалось в главе 2, расширители Atlas представляют собой компоненты,связывающие различные аспекты поведения (перетаскивание, всплывающие под-сказки и автозаполнение) с элементами ASP.NET. Аспект поведения (behavior) —

Page 86: Microsoft ASP.NET 2.0 AJAX

8 6 Глава 3. Частичное обновление страниц

компонент, всегда работающий на стороне клиента. Аспекты поведения привя-зываются к целевым элементам при помощи кода XML Script. Необходимый кодпривязки внедряется в страницу вручную или автоматически генерируется сер-вером для расширителя. В первом случае от разработчика потребуется знаниеXML Script. С другой стороны, при использовании серверных расширителей дос-таточно изучить программный интерфейс нового серверного элемента.

Обертки для клиентских компонентовБиблиотека Microsoft AJAX содержит множество клиентских элементов — та-ких, как текстовые поля и списки. Для настройки конфигурации и активизацииэтих клиентских элементов потребуется код JavaScript или XML Script. Если выпредпочитаете обойтись без лишнего кода, также можно использовать серверныеобертки для некоторых клиентских элементов Atlas.

Настройка свойств элементов осуществляется так же, как в классической мо-дели ASP.NET. Далее в соответствии с заданными свойствами элемент генериру-ет код XML Script для достижения желаемых целей.

Включение частичного обновления страницПростейший способ интеграции функциональности AJAX в новое или существую-щее приложение ASP.NET заключается в создании областей страницы, автоматиче-ски обновляемых при получении новых данных (тогда как остальная часть страницыостается неизменной). Механизм передачи данных работает так, как мы привык-ли видеть: пользователи щелкают на кнопках, серверная страница генерируетсяобычным образом и связывается с классом программной логики, практическиидентичным классу программной логики в стандартных приложениях ASP.NET.

Единственным новым элементом этого механизма является специализиро-ванный элемент управления — панель, которая взаимодействует с менеджеромсценариев Atlas и обновляет свои дочерние элементы при возврате данных. В ре-зультате текущая страница остается в прежнем виде, а разметка обновляемыхобластей автоматически заменяется по мере необходимости. Все это волшебствостановится возможным благодаря элементу UpdatePanel.

Элемент UpdatePanelКонтейнерный элемент UpdatePanel реализует возможность частичного измене-ния разметки в страницах ASP.NET. Такие страницы почти не отличаются отобычных страниц ASP.NET, если не считать того, что в них включается элементScriptManager и один или несколько элементов UpdatePanel. Каждый экземплярэлемента UpdatePanel задает области страницы, которые могут обновляться неза-висимо. Элементы UpdatePanel также могут размещаться внутри пользователь-ских элементов, на главной странице и на страницах содержимого.

Механизм частичного обновления разделяет страницу на независимые области.Каждая область самостоятельно управляет получением своих данных и обновляет-ся нужным образом без обновления всей страницы. Такое поведение желательнов тех ситуациях, когда при получении данных должна изменяться лишь часть

Page 87: Microsoft ASP.NET 2.0 AJAX

Включение частичного обновления страниц 8 7

страницы (возможно, весьма небольшая). Частичное обновление снижает объемперерисовки и помогает повысить степень интерактивности создаваемых приложе-ний. С точки зрения программиста эта схема позволяет принимать от сервера боль-ше возвратов данных, чем было бы возможно при полном обновлении страницы.

Общие сведения об элементе UpdatePanelЭлемент UpdatePanel определяется в сборке Microsoft.Web.Atlas, а в программноймодели он принадлежит пространству имен Microsoft.Web.UI. Класс элемента объ-является следующим образом:

public class UpdatePanel : Control{

}

Несмотря на логическое сходство с классическим элементом ASP.NET Panel,элемент Atlas UpdatePanel отличается от него по нескольким аспектам. В частности,он не является производным от Panel и, соответственно, не поддерживает некото-рых функций панелей ASP.NET (прокрутка, стили, управление содержимым и т. д.).Элемент Up+ лишь является контейнером для дочерних элементов, наделеннымподдержкой Atlas. Все необходимые стили и форматирование обеспечиваютсядочерними элементами. Вскоре мы разберем это обстоятельство более подробно.

Программный интерфейс элементаВ табл. 3.1 перечислены свойства элемента UpdatePanel, которые определяют кругаспектов поведения элемента, находящихся под управлением разработчика.

Таблица 3.1 . Свойства элемента UpdatePanel

Свойство ОписаниеContentTemplate Свойство определяет шаблон, то есть исходное содержимое UpdatePanelID Уникальное имя элемента, которое в дальнейшем может

использоваться для программных обращений к элементу (чтениеи запись). На стадии выполнения свойство ID не может изменятьсяпосле того, как элемент инициировал событие Init

IsUpdating Свойство указывает, находится ли панель в процессе обновленияпо асинхронному возврату данных

Mode Свойство определяет, при каких условиях происходит обновлениепанели (чтение и запись). Допустимые значения объединеныв перечисляемый тип UpdatePanelMode. По умолчаниюиспользуется режим Always

RenderMode Указывает, как генерируется содержимое панели — как встроенныйкод или в виде блока. Допустимые значения объединеныв перечисляемый тип UpdatePanelRenderMode. По умолчаниюиспользуется режим Block

Triggers Коллекция объектов-триггеров. Каждый объект предоставляетсобытие, приводящее к автоматическому обновлению панели

Page 88: Microsoft ASP.NET 2.0 AJAX

8 8 Глава 3. Частичное обновление страниц

В дополнение к свойствам, перечисленным в табл. 3.1, элемент UpdatePanelтакже поддерживает открытый метод с именем Update:

public void Update()

Метод сам по себе никаких специальных действий не выполняет, но запра-шивает обновление дочерних элементов, определенных в шаблоне содержимогоэлемента UpdatePanel. Используя метод Update, можно на программном уровнеуправлять обновлением области страницы в ответ на стандартное событие воз-врата данных или при инициализации страницы.

Элемент UpdatePanel не выдает нестандартные события. Поддерживаютсятолько события, производные от базового класса и общие для всех элементовASP.NET - In it, Load, PreRender, DataBinding и Unload.

Определение обновляемого содержимогоСодержимое панели UpdatePanel выражается специальным шаблоном — свойст-вом ContentTemplate. Шаблон обычно определяется на декларативном уровне,с использованием элемента <ContentTemplate>.

Впрочем, свойству ContentTemplate можно назначить любой объект, реали-зующий интерфейс ITemplate, в том числе и пользовательский элемент:

void Page_Load(object sender, EventArgs e){

UpdatePanel1.ContentTemplate = this.LoadTemplate(ascx);

}

В общем случае элементы ASP.NET, включенные в шаблон, остаются невиди-мыми на уровне страницы. Чтобы получить действительную ссылку на элемент,находящийся в шаблоне, следует вызвать метод FindControl для экземпляра эле-мента, содержащего шаблон. Рассмотрим следующий фрагмент кода:

<atlas:UpdatePanel id="UpdatePanell" runat="server" .„><ContentTemplate>

<asp:textbox runat="server" id="TextBoxl" ... /><asp:button runat="server" id="Buttonl" onclick="Buttonl_Click" ... />

</ContentTemplate></atlas:UpdatePanel>

Как вы думаете, что произойдет со следующим кодом на стадии выполнения?Отработает ли он нормально или вызовет исключение null-ссылки?

void Buttonl_Click(object sender, EventArgs e){

Response.Write(TextBoxl.Text);}

Элемент TextBoxl определяется внутри шаблона, и как следствие, остаетсяневидимым на уровне страницы. В ASP.NET 1.x попытка выполнения этогокода закончится сбоем; в ASP.NET 2.0 он может работать нормально, если свой-

Page 89: Microsoft ASP.NET 2.0 AJAX

Включение частичного обновления страниц 8 9

ство шаблона помечено атрибутом Templatelnstance. Как видно из следующегофрагмента, именно это происходит со свойством ContentTemplate элементаUpdatePanel:

[Browsable(false);[PersistenceMode(PersistenceMode.InnerProperty);[TempiateInstance(TemplateInstance.Single);public ITemplate ContentTemplate{

get { return _contentTemplate; }set { _contentTemplate = value; }

}

К любому элементу, определенному в свойстве ContentTemplate, можно обра-щаться напрямую из любого обработчика события, определенного в управляю-щей странице.

Режимы обновленияСвойство Mode определяет условия, при которых обновляется содержимое пане-ли. По умолчанию элемент UpdatePanel обновляет свое содержимое каждый раз,когда происходит возврат данных. Следовательно, если на странице находятсянесколько элементов UpdatePanel, они все будут обновлены — даже в том случае,если событие касается только одного из них.

Через свойство Mode элемент UpdatePanel поддерживает два режима обновле-ния — Always (используется по умолчанию) и Conditional. Значения объединеныв перечисление UpdatePanelMode (табл. 3.2).

Таблица 3.2. Перечисление UpdatePanelMode

Значение ОписаниеAlways Панель обновляется для каждого возврата данных, инициированного

страницейConditional Панель обновляется только при срабатывании триггеров панели

или при программном запросе на обновление

Содержимое панели может объединяться со страницей-носителем одним издвух способов — либо в виде встроенной разметки, либо на уровне блоков. Спо-соб выбирается при помощи свойства RenderMode, допустимые значения которо-го представлены в табл. 3.3.

Таблица 3.3. Перечисление UpdatePanelRenderMode

Значение ОписаниеBlock Содержимое панели заключается в тег <div>Inline Содержимое панели заключается в тег <span>

Page 90: Microsoft ASP.NET 2.0 AJAX

9 0 Глава 3. Частичное обновление страниц

По умолчанию содержимое панели образует новый блок и заключается в тег<div>:

<div id="UpdatePanell">

</div>

Если будет выбрано значение Inline, содержимое встраивается в поток кодастраницы, как показано в следующем примере:

<form id="forml" runat="server"><atlas:ScriptManager runat="server" ID="scriptManager" />

<big>This panel has been generated at:<atlas:UpdatePanel ID="UpdatePanell" runat="server"

rendermode="inline"><ContentTemplate>

<b style="background-color:lime"><% =DateTime.Now %></b>

</ContentTemplate></atlas:UpdatePanel>.

</big>

<hr /><asp:Button ID="Buttonl" runat="server" Text="Refresh" />

</form>

Результат работы приведенного фрагмента показан на рис. 3.1. Обновляемаячасть страницы представляет собой не блок разметки, а простой фрагмент абзаца.

Рис. 3 . 1 . Использование элемента UpdatePanel для частичного обновления текста абзаца

Проверка текущих обновленийЛогическое свойство IsUpdating The IsUpdating read-only Boolean property ука-зывает, находится ли содержимое элемента UpdatePanel в процессе обновления.Свойство проверяется при обработке возврата данных; если свойство возвраща-ет true, значит, текущий запрос выполняется в результате возврата данных Atlas.

Page 91: Microsoft ASP.NET 2.0 AJAX

Включение частичного обновления страниц 9 1

Элементы UpdatePanel могут быть вложены в другие элементы UpdatePanel.Вложенная панель всегда обновляется в случае обновления внешней родитель-ской панели. В этом случае свойство IsUpdating остается равным false. У вложен-ных панелей IsUpdating может быть равно true только в том случае, если родительне нуждается в обновлениях.

Использование элемента UpdatePanelОдного размещения элемента UpdatePanel на странице еще недостаточно для ак-тивизации частичного обновления. Вы также должны разместить на страницеэлемент ScriptManager и убедиться в том, что его свойству EnablePartialRenderingзадано значение true. Страница ASP.NET может содержать несколько элементовUpdatePanel; это позволяет разбить страницу на несколько областей, обновляе-мых независимо друг от друга, и даже по особым условиям.

ПРИМЕЧАНИЕЕсли свойству EnablePartialRendering элемента ScriptManager задано значение false(используемое по умолчанию), то элемент UpdatePanel работает как обычная панельASP.NET. Если вам вдруг показалось, что UpdatePanel работает некорректно (скажем,обновленное содержимое мерцает в процессе обновления), наиболее вероятная причи-на заключается именно в этом.

Первый пример страницы с частичным обновлениемДопустим, на вашей странице определена область (скажем, блок <div>), в кото-рой отображается информация реального времени, нуждающаяся в частом об-новлении. На странице также размещается кнопка, обновляющая критическуюинформацию. В классических страницах ASP.NET эта схема реализуется так:

<form id="forml" runat="server"><hl>What time is it worldwide? [Using postback]</hl><asp:panel runat="server" style="background-color:Lime">

<hl><asp:Label ID="Labell" runat="server"

Text="What time is on the server?" /></hl><asp:Button ID="Buttonl" runat="server"

Text="Read time on the server"OnClick="Buttonl_Click" />

</asp:panel><h3>This page has been generated at: <^=DateTime.Now ^></h3>

</form>

Элемент Panel содержит два элемента, надпись (Label) и кнопку (Button).Когда пользователь щелкает на кнопке, на сервере выполняется код обновлениянадписи. Однако в классической схеме ASP.NET каждый щелчок на кнопке при-водит к обновлению всей страницы.

ASP.NET Atlas позволяет отделить часть страницы, нуждающуюся в обнов-лении, и заключить ее в элемент UpdatePanel. В результате по щелчку будет

Page 92: Microsoft ASP.NET 2.0 AJAX

9 2 Глава 3. Частичное обновление страниц

обновляться только содержимое панели. Вот как выглядит версия предыдущейформы с поддержкой Atlas:

<form id="forml" runat="server"><atlas:ScriptManager runat="server" ID="scriptManager"

EnablePartialRendering="true" /><hl>What time is it worldwide? [Using Atlas]</hl><atlas:UpdatePanel ID="UpdatePanell" runat="server">

<ContentTemplate><div style="background-color:Lime"><hl><asp:Label ID="Label1" runat="server"

Text="What time is on the server?" /></hl><asp:Button ID="Buttonl" runat="server"

Text="Read time on the server"OnClick="Buttonl_Click" />

</div></ContentTemplate>

</atlas:UpdatePanel><h3>This page has been generated at: <^=DateTime.Now ^></h3>

</form>

В сущности, содержимое тега <asp:Panel> переместилось в секцию <Content-Template> элемента UpdatePanel, и на странице добавился элемент ScriptManager.Изменения невелики, но их последствия весьма значительны.

На рис. 3.2 показана страница в действии. Обратите внимание: страница и па-нель были сгенерированы в разное время. Это означает, что после того, какстраница была создана и отображена в браузере, пользователь щелкнул на кноп-ке с целью получения времени на сервере. Содержимое панели регенерируется,но большая часть страницы осталась в прежнем виде.

Рис. 3.2. Пример страницы с элементом UpdatePanel

Глагол «регенерируется» в данном случае более уместен, чем кажется напервый взгляд. Разметка сегмента страницы, внедренная в элемент UpdatePanel,

Page 93: Microsoft ASP.NET 2.0 AJAX

Включение частичного обновления страниц 9 3

действительно регенерируется (то есть генерируется заново) на сервере вслед-ствие запроса Atlas. Сгенерированная разметка вставляется в ответ HTTP и воз-вращается клиенту. Инфраструктура Atlas обрабатывает его и обновляет стра-ницу.

Как работает механизм частичного обновленияВолшебство обновления отдельных частей страницы строится на совместныхусилиях элемента UpdatePanel и компонента Atlas ScriptManager. В фазе ини-циализации элемент UpdatePanel получает ссылку на компонент ScriptManagerстраницы и регистрируется в нем. В результате ScriptManager знает, сколькообновляемых панелей содержит страница, и хранит ссылки на каждую из них.

Компонент ScriptManager также генерирует код клиентского сценария для пе-рехвата любых действий отправки данных, инициированных на стороне клиента.Сценарный код подключается к событию формы submit и заменяет отправкуданных асинхронным вызовом Atlas, выполняемым через объект XmlHttpRequest.В следующем листинге показан код XML Script, внедряемый в клиентскую стра-ницу при включении частичного обновления:

<script type="text/xml-script"><page xmlns:script="http://schernas.niicrosoft.coni/xnil-script/2005">

<components><pageRequestManager id="_PageRequestManager"

UpdatePanelIDs="UpdatePanell" asyncPostbackControlIDs=""scriptManagerID="scriptManager" form="forml" />

</components></page>

</script>

Элемент <pageRequestManager> содержит ссылку на экземпляр класса Page-RequestManager из библиотеки Microsoft AJAX. В частности, этот класс отвечаетза асинхронные вызовы для обновления (полного или частичного) текущей стра-ницы через объект XmlHttpRequest.

Среди прочего, класс подключает новые обработчики к событиям формыonsubmit и onclick. Вы можете ознакомиться с фактической реализацией класса,просмотрев исходный код в файле atlas.js или класс из пространства имен Sys.WebForms в электронной документации Atlas.

Тело запроса, отправленного серверу, выглядит примерно так:scriptManager=Update&VIEWSTATE=^2Fw ... 3D&EVENTVALIDATI0N=^2Fw ... 3D&

Buttonl=Read^20time^20oru20the^20server

Помимо состояния отображения (VIEWSTATE) и данных проверки событий(EVENTVALIDATION), специфических для ASP.NET 2.0, запрос содержит имя эле-мента HTML, инициировавшего отправку данных (Button"!), и идентификаторэлемента ScriptManager, обрабатывающего вызов. Чтобы просмотреть все со-ставляющие запроса, либо воспользуйтесь специальной утилитой отслеживания

Page 94: Microsoft ASP.NET 2.0 AJAX

9 4 Глава 3. Частичное обновление страниц

трафика (см. главу 2), либо просто включите отладочный код в обработчиксобытия Page_Load:

protected void Page_Load(object sender, EventArgs e){

Request.SaveAs(@"c:\req_details.txt", true);}

На сервере запрос обрабатывается как обычно; в самом деле, runtime-средаASP.NET не может определить, что запрос предназначен для обновления толькочасти исходной страницы.

Менеджер сценариев подключается к стандартному процессу построения стра-ницы кода посредством регистрации метода обратного вызова. Эта малоизвест-ная возможность присутствует в ASP.NET с первых дней появления платформы,а реализуется она методом SetRenderMethodDelegate класса Page. Измененныйпроцесс построения страницы перебирает все зарегистрированные обновляемыепанели и приказывает каждой из них вывести обновленную разметку.

В конечном итоге клиент возвращает только содержимое обновляемых облас-тей, а функция обратного вызова JavaScript, скрытая в недрах библиотеки Micro-soft AJAX, обеспечивает замену текущего содержимого областей принятой раз-меткой.

ПРИМЕЧАНИЕИз-за особенностей внутреннего устройства элемента UpdatePanel в шаблон содержи-мого запрещается включать элемент FileUpload. В противном случае процесс загрузкиданных нарушит работу частичного обновления и создаст проблемы с синхронизацией.Впрочем, элемент FileUpload может находиться на одной странице с элементом Update-Panel — при условии, что он размещается за пределами шаблона содержимого панели.

Более реальный пример страницыс частичным обновлениемМногие элементы ASP.NET содержат элементы, активизируемые щелчком, — та-кие, как кнопки и ссылки. Взаимодействие пользователя с разметкой таких эле-ментов приводит к отправке данных и полному обновлению всей страницы. Осо-бенно дорогостоящими в отношении загрузки канала, задержки и потреблениявычислительных мощностей сервера являются сетки (табличные элементы) вро-де DataGrid и GridView. Они могут генерировать многостраничный вывод, и поль-зователю нередко приходится снова щелкать и передавать запрос для просмотрасодержимого определенной страницы. Существует ли способ получения постра-ничного, отсортированного или отфильтрованного представления содержимогосеток без полного обновления всей страницы?

В ASP.NET 2.0 элемент GridView содержит логическое свойство с именем Enable-SortingAndPagingCallbacks. При установке этого свойства элемент активизируетмеханизм обратного вызова на стороне клиента для операций сортировки и по-страничного вывода. Содержимое отдельного страничного блока данных эле-мента запрашивается с сервера, но разметка элемента обновляется без полного

Page 95: Microsoft ASP.NET 2.0 AJAX

Включение частичного обновления страниц 9 5

обновления страницы. В ASP.NET 2.0 эта функция реализуется на базе ASP.NETScript Callback. Давайте посмотрим, как добиться подобного результата в при-кладной среде Atlas:

<form id="forml" runat="server"><atlas:ScriptManager ID="scriptManager" runat="server"

EnablePartialRendering="true" />

<atlas:UpdatePanel ID="UpdatePanell" runat="server"><ContentTemplate>

<asp:GridView ID="GridViewl" runat="server"DataSourceID="ObjectDataSourcel" AllowPaging="True"AutoGenerateColumns="False">

<Columns><asp:BoundField DataField="ID"

HeaderText="ID" /><asp:BoundField DataField="CompanyName"

HeaderText="Company" /><asp:BoundField DataField="Country"

HeaderText="Country" /></Columns>

</asp:GridView><asp:ObjectDataSource ID="ObjectDataSourcel" runat="server"

TypeName="IntroAtlas.CustomerManager"SelectMethod="LoadAll" />

</ContentTemplate></atlas:UpdatePanel>

</form>

В секцию ContentTemplate элемента UpdatePanel включены элементы GridViewи ObjectDataSource. Первый элемент обеспечивает отображение в табличномформате гиперссылок на данные, полученные вторым элементом. Установкасвойства AllowPaging равным true включает элементы перехода между страни-цами данных в сетке. Щелкнув на любой гиперссылке, пользователь переходитк соответствующему страничному блоку набора данных. Обычно за это действиеприходится расплачиваться обновлением всей страницы; но поскольку в данномслучае сетка инкапсулирована в элементе UpdatePanel, при щелчке инициирует-ся упрощенный внеполосный вызов, а обновляются только элементы в секцииControlTemplates.

ПРИМЕЧАНИЕСамой интересной особенностью данного примера является не функциональность кактаковая, а тот факт, что в элементе UpdatePanel можно разместить практически любуюкомбинацию элементов ASP.NET. Если какой-либо из этих элементов инициирует от-правку данных с обновлением страницы, то соответствующий сегмент страницы будетобновляться независимо от остальных участков. Кроме того, реализация такого реше-ния не требует специальных знаний среды Atlas.На первый взгляд может показаться, что элемент UpdatePanel в целом повторяет функ-циональность свойства EnableSortingAndPagingCallbacks. Тем не менее он обладаетмного большей гибкостью и может применяться в гораздо более широком диапазонеситуаций.

Page 96: Microsoft ASP.NET 2.0 AJAX

9 6 Глава 3. Частичное обновление страниц

Управление обновлением страницДо настоящего момента мы рассматривали страницы с единственным элементомUpdatePanel; при этом подразумевалось, что все панели частичного обновлениядолжны обновляться при каждом возврате данных. Однако более реалистичнобыло бы предположить, что страница может содержать несколько таких пане-лей. Кроме того, обновление панелей может инициироваться элементами, рас-пределенными по странице и совершенно не обязательно находящимися внутрипанели.

Наконец, на практике панели часто логически привязываются к заранее из-вестному набору триггеров (щелчки на кнопках, изменения значений, событияHTML) и обновляются только при наличии активных триггеров из этого на-бора. Давайте посмотрим, как взять процесс обновления страницы под полныйконтроль, а заодно познакомимся поближе с триггерами и условным обновлени-ем панелей.

Обновление панели по триггеруВо всех примерах, рассматривавшихся до настоящего момента, элемент, которыйявлялся причиной асинхронного возврата данных, всегда располагался внутриобновляемой панели. На практике это условие выполняется далеко не всегда.Панель может обновляться по щелчку на любом элементе страницы, которыйможет стать причиной возврата данных. Если элемент находится за пределамипанели, произойдет полное обновление страницы — если только элемент не былзарегистрирован в качестве триггера обновления для панели.

Использование внешних кнопокЧтобы содержимое панели обновлялось при щелчке на внешней кнопке (то естьна кнопке, находящейся за пределами панели), кнопка регистрируется в качест-ве триггера для панели:

<asp:button runat="server" id="ExternalButton" text="Click"onclick="ExternalButton_Click" />

<atlas:UpdatePanel runat="server"><ContentTemplate>

</ContentTemplate><Triggers>

<atlas:ControlEventTrigger ControlID="ExternalButton"EventName="Click" />

</Triggers></atlas:UpdatePanel>

Для каждого элемента UpdatePanel можно определить сразу несколько тригге-ров. При срабатывании любого из них панель автоматически обновляется. Триг-геры UpdatePanel могут определяться как на декларативном, так и на программ-ном уровне. В первом варианте используется секция <Triggers>, а во втором — свойство-коллекция Triggers (см. табл. 3.1).

Page 97: Microsoft ASP.NET 2.0 AJAX

Управление обновлением страниц 9 7

На основании приведенного кода панель будет обновляться либо в том слу-чае, если возврат данных был инициирован изнутри панели, либо по щелчку навнешней кнопке ExtemalButton.

Триггеры UpdatePanelТриггер панели UpdatePanel определяет событие, приводящее к обновлению эле-мента UpdatePanel при работе страницы в режиме частичного обновления. Atlasподдерживает два типа триггеров, ControlEventTrigger и ControlValueTrigger; обаявляются потомками абстрактного класса UpdatePanelTrigger. Точнее говоря, двакласса триггеров наследуют от промежуточного класса ControlTrigger, который,в свою очередь, наследует от UpdatePanelTrigger, как показано на рис. 3.3.

ControlEventTrigger ControlValueTrigger

ControlTrigger Прочие

UpdatePanelTrigger

Рис. 3.3. Иерархия классов триггеров

Прикладная среда Atlas определяет небольшую группу триггеров, функцио-нальность которых связана с поведением серверных элементов. Впрочем, иерар-хия триггеров готова к определению сторонних триггеров, основанных на другойфункциональности — cкажем, на изменениях в кэше, в файлах или в базе данных.

Триггеры событийКласс ControlValueTrigger представляет триггер, обновляющий содержимое эле-мента UpdatePanel по событию серверного элемента. Декларативное определениетриггера осуществляется в секции <Triggers> элемента UpdatePanel:

<atlas:UpdatePanel runat="server"><ContentTemplate>

</ContentTemplate><Triggers>

<atlas:ControlEventTrigger ControlID="DropDownListl"EventName="SelectedIndexChanged" />

</Triggers></atlas:UpdatePanel>

В объявлении триггера необходимо указать два значения: идентификатор от-слеживаемого элемента и перехватываемое событие. Значения ControllD и Event-Name представляют собой строковые свойства. Панель, описанная в предыдущем

Page 98: Microsoft ASP.NET 2.0 AJAX

9 8 Глава 3. Частичное обновление страниц

фрагменте кода, обновляется либо в том случае, если возврат данных был ини-циирован изнутри панели, либо при изменении текущего выбора в раскрываю-щемся списке с именем DropDownListl.

Важно заметить, что ControlEventTrigger перехватывает только события на сто-роне сервера, обладающие следующей сигнатурой:

void handler(object sender, EventArgs e);

Но при этом следует учесть, что аргумент е может относиться к любому клас-су, производному от EventArgs. Давайте создадим более содержательный примерна базе примера с сеткой, который рассматривался несколько ранее в этой главе.

Допустим, имеется многостраничная сетка со списком всех клиентов. Сетканаходится внутри контейнера UpdatePanel, чтобы пользователь мог просматри-вать информацию по группам клиентов без полного обновления всей страницы.

Теперь задача усложняется — для сетки требуется организовать дополнитель-ную фильтрацию по строковому критерию. Допустим, во вспомогательном тек-стовом поле вводится буква «A», а в сетке появляются имена всех клиентов, на-чинающихся с этой буквы. Не стоит и говорить, что это должно происходить безполного обновления всей страницы. Следующий фрагмент разметки закладыва-ет основу для решения этой задачи:

<form id="forml" runat="server"><atlas:ScriptManager ID="scriptManager" runat="server"

EnablePartialRendering="true" />

Query string:<br /><asp:TextBox ID="TextBoxl" runat="server"

OnTextChanged="TextBoxl_TextChanged" /><asp:Button ID="Buttonl" runat="server" Text="Refresh" />

<atlas:UpdatePanel ID="UpdatePanell" runat="server"><ContentTemplate>

<asp:GridView ID="GridViewl" runat="server"DataSourceID="ObjectDataSourcel" AllowPaging="True"AutoGenerateColumns="False" ><FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" /><Columns>

<asp:BoundField DataField="ID"HeaderText="ID" />

<asp:BoundField DataField="CompanyName"HeaderText="Company" />

<asp:BoundField DataField="Country"HeaderText="Country" />

</Columns></asp:GridView>

<asp:ObjectDataSource ID="ObjectDataSourcel" runat="server"TypeName="IntroAtlas.CustornerManager"SelectMethod="LoadAll">

</asp:ObjectDataSource></ContentTemplate>

Page 99: Microsoft ASP.NET 2.0 AJAX

Управление обновлением страниц 9 9

<Triggers><atlas:ControlEventTrigger ControlID="TextBoxl"

EventName="TextChanged" /><atlas:ControlEventTrigger ControlID="Buttonl"

EventName="Click" /></Triggers>

</atlas:UpdatePanel></form>

По сравнению со страницей, рассматривавшейся ранее, в этом коде доба-вилось текстовое поле, инициирующее триггерное событие наряду с кнопкой.Триггер связывается с событием TextChanged текстового поля. Панель обнов-ляется как при возврате данных страницей, так и при срабатывании событияTextChanged. Событие TextChanged само по себе не вызывает возврата данных,поэтому в этом случае все равно потребуется щелчок на кнопке. Чтобы предот-вратить полное обновление страницы, событие Click кнопки регистрируется в ка-честве триггера для панели:

protected void Page_Load(object sender, EventArgs e){

// Восстановление исходной ситуации для предотвращения null-ссылокObjectDataSourcel.SelectMethod = "LoadAll";ObjectDataSourcel.SelectParameters.Clear();

}protected void TextBoxl_TextChanged(object sender, EventArgs e){

// Изменение метода, используемого для заполнения сеткиObjectDataSourcel.SelectMethod = "LoadBylnitial";ControlParameter p = new ControlParameter("query", "TextBoxl", "Text");ObjectDataSourcel.SelectParameters.Add(p);

}

При срабатывании TextChanged мы изменяем метод заполнения для элементаObjectDataSource, используемого для заполнения сетки, и передаем в качествепараметра текущее значение свойства Text элемента TextBox. Результаты показа-ны на рис. 3.4 и 3.5.

Триггеры значенийКласс ControlValueTrigger представляет триггер, изменяющий содержимое элемен-та UpdatePanel в ответ на изменение значения заданного свойства элемента. Дек-ларативное определение триггера осуществляется в секции <Triggers> элементаUpdatePanel:

<atlas:UpdatePanel runat="server"><ContentTemplate>

</ContentTemplate><Triggers>

<atlas:ControlValueTrigger ControlID="TextBoxl"PropertyName="Text" />

</Triggers></atlas:UpdatePanel>

Page 100: Microsoft ASP.NET 2.0 AJAX

1 0 0 Глава 3. Частичное обновление страниц

Рис. 3.4. Сетку с полным списком клиентов можно прокручиватьбез полного обновления страницы

3 Event triggers - Microsoft Internet Explorer - J|_ISFile Edit View Favorites Tools Help If

В Ш & P5earl:n i^ Favorites »

Address Щ] http://localhost:1386/IntroAtlas/5a v 0Go L nks >J

Query str ing:

dJ

v К Refresh |]

dJ

ID Company Country

dJ

VAFFE Vafferjernet Denmark

dJ

VICTE Victuailles en stock France

dJ

VINET Vins et alcools Chevalier France

dJdJШ\ Done V j Local intranet

Рис. 3.5. Если ввести в текстовом поле критерий фильтрации, содержимоесетки обновляется без полного обновления страницы

Page 101: Microsoft ASP.NET 2.0 AJAX

Управление обновлением страниц 1 0 1

В объявлении триггера необходимо указать два значения: идентификаторэлемента и имя свойства, изменения которого должны отслеживаться. ЗначенияControllD и PropertyName представляют собой строковые свойства. Если значениеPropertyName не задано, используется свойство элемента по умолчанию (такоесвойство, если оно есть, помечается атрибутом ControlValueProperty).

Условное обновлениеКогда свойству Mode задано значение Always, каждый возврат данных, иниции-рованный со страницы (как с элементов внутри панели, так и вне ее), приводитк обновлению панели. Если свойству Mode задано значение Conditional, панельобновляется только в том случае, если при возврате данных был вызван методUpdate, или при срабатывании триггера, связанного с элементом UpdatePanel.

Активизация условных обновленийЕсли на странице находится только один элемент UpdatePanel, проблема услов-ного обновления не актуальна. Тем не менее, если страница содержит несколькопанелей, придется позаботиться о том, чтобы каждая панель обновлялась тольков случае необходимости.

Для включения условных обновлений свойству Mode элемента UpdatePanelзадается значение Conditional (по умолчанию используется значение Always).

<atlas:UpdatePanel runat="server" Mode="Conditional">

</atlas:UpdatePanel>

Условное обновление производится на уровне триггеров или на программномуровне. При использовании триггеров вы определяете список событий, приводя-щих к обновлению панели. С другой стороны, чтобы реализовать условное об-новление на программном уровне, следует вызвать метод Update для панели придостижении некоторой критической точки в ходе выполнения.

Независимое обновление нескольких панелейДавайте доработаем страницу с сеткой, описанную ранее, и поместим на нее вто-рой элемент UpdatePanel:

<atlas:UpdatePanel ID="UpdatePanell" runat="server" Mode="Conditional"><ContentTemplate>

</ContentTemplate><Triggers>

<atlas:ControlEventTrigger ControlID="TextBoxl"EventName="TextChanged" />

<atlas:ControlEventTrigger ControlID="Buttonl"EventName="Click" />

</Triggers></atlas:UpdatePanel>

<atlas:UpdatePanel ID="UpdatePanel2" runat="server" Mode="Conditional"><ContentTemplate>

Page 102: Microsoft ASP.NET 2.0 AJAX

1 0 2 Глава 3. Частичное обновление страниц

<div stylе="background-color:Lime"><big>This panel has been generated at: <^=DateTime.Now ^></big>

</div></ContentTemplate><Triggers>

<atlas:ControlEventTrigger ControlID="Button2"EventName="Click" />

</Triggers></atlas:UpdatePanel>

<asp:Button ID="Button2" runat="server" Text="Refresh time"0nClick="Button2_Click" />

У второго элемента UpdatePanel событие Click кнопки Button2 определяетсякак триггер. Для обеих панелей активизирован режим условного обновления.Рассмотрим их поведение более подробно.

Первая панель обновляется при инициировании события TextChanged для тек-стового поля. Обратите внимание на интересную подробность: сетка не обновля-ется при щелчках на кнопках навигации. После того как панель была помеченадля условного обновления, она обновляется только по явно заданным событиям.

В конечном итоге, чтобы разрешить постраничную навигацию в сетке, необ-ходимо добавить новый триггер для события PagelndexChanged сетки:

<Triggers><atlas:ControlEventTrigger ControlID="TextBoxl"

EventName="TextChanged" /><atlas:ControlEventTrigger ControlID="Buttonl"

EventName="Click" /><atlas:ControlEventTrigger ControlID="GridViewl"

EventName="PagelndexChanged" /></Triggers>

Вторая панель обновляется только при щелчке на нижней кнопке или приполном возврате данных. Программный запрос на обновление панели реализует-ся следующим образом:

protected void ButtonlJClick(object sender, EventArgs e){

UpdatePanel2.UpdateO;}

К этому решению следует прибегать только в том случае, если между двумяпанелями существует неявная зависимость. В этом случае во время обновленияодной панели могут возникнуть условия, требующие обновления другой панели.Так как на этой стадии код выполняется на сервере, задачу невозможно решитьдругим способом, кроме явного вызова метода Update для панели.

На рис. 3.6 изображена страница с несколькими панелями.На рисунке пользователь собирается щелкнуть на кнопке для обновления вто-

рой панели. Однако содержимое элемента TextBox изменилось — в поле был вве-ден текст «v». При возврате данных страницей проверяется новое содержимоеTextBox, и в случае обнаружения события TextChanged сетка также обновляется.

Page 103: Microsoft ASP.NET 2.0 AJAX

Обратная связь во время обновления 1 0 3

Рис. 3.6. Два элемента UpdatePanel на одной странице

Обратная связь во время обновленияС точки зрения пользователя с обновлением панели дело обстоит не столь глад-ко. Выполнение компьютером потенциально продолжительной операции создаетпроблемы. Устоит ли пользователь перед искушением снова и снова щелкать накнопке? Сможет ли он терпеливо дожидаться появления результатов? Наконец,захочется ли ему ждать, не имея ни малейшего представления о происходящем,не вызовет ли это раздражения? В процессе полного возврата данных браузеробычно каким-то образом сообщает пользователю о происходящем. При исполь-зовании Atlas частичное обновление не приводит к полному возврату данных,поэтому визуальная обратная связь не оповещает пользователя о происходящихсобытиях.

Помните, что Atlas представляет собой воплощение парадигмы AJAX наплатформе ASP.NET, а в сокращении AJAX буква «A» означает «асинхронный».Следовательно, разработчик Atlas должен тщательно продумать, как оповеститьпользователя о ходе выполняемых операций, и по возможности предоставитьвозможность отмены незавершенных запросов.

Page 104: Microsoft ASP.NET 2.0 AJAX

1 0 4 Глава 3. Частичное обновление страниц

Для обеспечения обратной связи с пользователем в Atlas существует элементUpdateProgress, предназначенный для вывода шаблонного содержимого на времяобновления панелей страницы.

Элемент UpdateProgressЭлемент UpdateProgress обеспечивает обратную связь в браузере во время обнов-ления одного или нескольких элементов UpdatePanel. Элемент UpdateProgressможно разместить в любом месте страницы, определяя его стиль и позицию припомощи каскадных таблиц стилей (CSS).

Общие сведения об элементе UpdateProgressЭлемент UpdateProgress определяется в пространстве имен Microsoft.Web.UI и пре-доставляется сборкой Microsoft.Web.Atlas. Он является производным от классаControl и реализует пару интерфейсов:

public class UpdateProgress : Control, INamingContainer, IScriptControl

Специфический интерфейс Atlas IScriptControl описывает нестандартный сервер-ный элемент как элемент Atlas. Интерфейс содержит всего один метод RenderScript,который должен генерировать весь необходимый для элемента код XML Script.

Страница может содержать не более одного элемента UpdateProgress, кото-рый обслуживает все обновляемые панели на странице. Если страница содержитнесколько панелей, постарайтесь найти удобное место на странице для Update-Progress или, если возможно, переместите его на программном уровне в нужноеместо к обновляемой панели.

Элемент UpdateProgress обладает единственным свойством ProgressTemplate.Свойство определяет шаблон с разметкой, которая должна отображаться во вре-мя обновления панели.

Вывод информации о ходе операцииAtlas отображает содержимое шаблона ProgressTemplate во время ожидания об-новления панели. Шаблон определяется либо декларативно, либо на программ-ном уровне. Во втором случае свойству задается любой объект, реализующийинтерфейс ITemplate. В первом случае разметка легко задается декларативнымспособом, как показано в следующем фрагменте:

<atlas:UpdateProgress runat="server" ID="UpdateProgressl"><ProgressTemplate>

</ProgressTemplate></atlas:UpdateProgress>

Шаблон может содержать произвольную комбинацию элементов. Впрочем,обычно в него помещается небольшой текстовый фрагмент и анимированноеизображение в формате GIF (рис. 3.7).

Связь между элементом UpdatePanel и UpdateProgress устанавливается ав-томатически. Учтите, что элемент UpdateProgress спроектирован не как класси-

Page 105: Microsoft ASP.NET 2.0 AJAX

Обратная связь во время обновления 1 0 5

ческий индикатор процесса, а как определяемая пользователем панель, котораяотображается элементом ScriptManager перед началом обновления и скрываетсясразу же после его завершения.

Рис. 3.7. Шаблон сообщает пользователю, что сервер в настоящий момент занят

ПРИМЕЧАНИЕВнешний вид и поведение элемента UpdateProgress можно настраивать динамически(до определенной степени). Для этого необходимо написать обработчик события Loadэлемента UpdateProgress и получить ссылку на элементы шаблона методом FindControl.Аналогичным образом можно сменить анимированное изображение и выбрать то, ко-торое лучше отображает текущий контекст.

Отмена незавершенного обновленияСистема, действительно рассчитанная на удобство пользователя, всегда позволя-ет пользователям отменять незавершенные операции. Как добиться этой целис элементом UpdateProgress? На шаблоне размещается кнопка отмены. В страни-цу внедряется сценарный код, который отслеживает состояние кнопки и при об-наружении щелчка прерывает текущую асинхронную операцию.

Page 106: Microsoft ASP.NET 2.0 AJAX

1 0 6 Глава 3. Частичное обновление страниц

Чтобы шаблон содержал кнопку отмены, в него включается следующий тег:<input id="abortButton" runat="server" type="button"value="Cancel" />

Прежде всего, для отмены используется кнопка клиентской стороны. Следо-вательно, она может быть представлена как элементом <input>, так и элементом<button> для браузеров, поддерживающих этот элемент. Если вы выберете эле-мент <input>, атрибут type должен быть задан равным button. Чтобы кнопка былаидентифицирована как кнопка отмены в Atlas, атрибут id должен быть равенabortButton. Наконец, атрибут runat должен содержать текст server.

На рис. 3.8 показана панель с кнопкой отмены текущей операции.

Рис. 3.8. Отмена незавершенного обновления

Менеджер сценариев связывает специально сгенерированный сценарный кодс событием onclick кнопки отмены. Далее при щелчке на кнопке асинхроннаяоперация отменяется через стандартный API объекта XmlHttpRequest.

Page 107: Microsoft ASP.NET 2.0 AJAX

Таймер 107

ПРИМЕЧАНИЕЭлемент UpdateProgress прост в использовании и эффективен, однако он скрывает не-которые действия, которые могут быть крайне существенными в некоторых случаях.Например, автор страницы не может связать пользовательский код с отображениемшаблона. Например, такая возможность могла бы пригодиться для блокировки актив-ных элементов или запуска второго, параллельного асинхронного вызова. Для чего этоможет понадобиться? Например, для реализации контекстно-чувствительного индика-тора процесса во время продолжительной операции.

ТаймерНа страницах ASP.NET, требующих частого обновления, можно разместить эле-менты, активизируемые по щелчку; пользователь запрашивает обновление тогда,когда сочтет нужным. Но что, если обновление должно происходить часто и с ре-гулярными интервалам — скажем, каждые n миллисекунд? Нельзя же требовать,чтобы пользователь постоянно щелкал мышью. В подобных ситуациях на помощьприходят таймеры. Кстати, поддержка таймеров присутствовала в модели DOMпрактически любого браузера с первых дней существования Web.

Клиентский таймер создается методом setTimeout объекта DOM window. За-пущенный таймер периодически выполняет фрагмент кода JavaScript. В своюочередь, этот сценарный код может сделать все, что сочтет нужным — например,запустить асинхронный вызов к серверу и автоматически обновлять страницу.

Сценарные таймеры можно использовать в любой версии ASP.NET, однакодля этого необходимо обладать навыками программирования на JavaScript и знатьособенности модели DOM браузера. Atlas избавляет вас от всех сложностей и пре-доставляет в ваше распоряжение специальный компонент TimerControl.

Общие сведения об элементе TimerControlЭлемент TimerControl определяется в пространстве имен Microsoft.Web.Ul.Controlsи предоставляется сборкой Microsoft.Web.Atlas. Он наследует от класса Controlи реализует интерфейсы IPostBackEventHandler и IScriptControl.

public class TimerControl : Control,IPostBackEventHandler, IScriptControl

TimerControl реализуется как серверный элемент, но в действительности онсоздает на стороне клиента таймер, выполняющий возврат данных с регулярны-ми интервалами. При возврате серверный элемент TimerControl инициирует сер-верное событие с именем Tick.

public event EventHandler Tick

Элемент обладает двумя свойствами, описанными в табл. 3.4.В сущности, TimerControl представляет собой серверный интерфейс, постро-

енный на базе клиентского таймера. Он избавляет разработчика от необходимо-сти создавать таймер на уровне сценарного кода и заставляет его возвращатьданные при истечении интервала.

Page 108: Microsoft ASP.NET 2.0 AJAX

1 0 8 Глава 3. Частичное обновление страниц

Таблица 3.4. Свойства элемента TimerControl

Свойство ОписаниеEnabled Свойство указывает, нужно ли генерировать клиентский сценарий таймера

при первоначальном построении страницы (по умолчанию true)Interval Целочисленное свойство, определяющее интервалы между событиями Tick

клиентского таймера. Интервал выражается в миллисекундах, значение поумолчанию — 60 000 (одна минута)

Использование таймераЭлемент TimerControl чаще всего используется в сочетании с триггером Update-Panel для обновления панели с заданной периодичностью. В следующем фраг-менте определяется таймер, который инициирует ответное обращение каждуюсекунду:

<atlas:TimerControl ID="timerl" runat="server"Interval="1000" 0nTick="timerl_Tick" />

Очень важно тщательно проанализировать влияние слишком короткого ин-тервала на общую производительность и масштабируемость приложения. Выборслишком малого значения (например, одна или две секунды) порождает слиш-ком много ответных обращений и увеличивает трафик на пути к серверу. В ре-зультате даже асинхронные обращения, выполняемые в режиме частичного об-новления, приводят к лишним непроизводительным затратам.

В следующем примере элемент UpdatePanel работает в сочетании с таймером(TimerControl). Таймер срабатывает каждую секунду. Элемент UpdatePanel связы-вается с событием Tick таймера при помощи событийного триггера:

<form id="forml" runat="server"><atlas:ScriptManager ID="scriptManager" runat="server"

EnablePartialRendering="true" />

<atlas:UpdatePanel ID="UpdatePanell" runat="server" Mode="Conditional"><ContentTemplate>

<hl><asp:Label ID="Label1" runat="server" />

</hl></ContentTemplate>

<Triggers><atlas:ControlEventTrigger ControlID="Timerl"

EventName="Tick" /></Triggers>

</atlas:UpdatePanel>

<atlas:TimerControl ID="Timerl" runat="server" Interval="1000"0nTick="Timerl_Tick" />

</form>

В результате панель обновляется каждую секунду. Иначе говоря, на сервереежесекундно выполняется следующий код:

protected void Timerl_Tick(object sender, EventArgs e){

Page 109: Microsoft ASP.NET 2.0 AJAX

Заключение 1 0 9

_abell.Text = DateTime.Now.ToStringO;}

На рис. 3.9 показано, как выглядит эта страница в действии.

Рис. 3.9. Часы на базе Atlas в действии

ЗаключениеПо своей сущности Atlas является клиентской средой, в которой JavaScript играетключевую роль. Чтобы извлечь максимум пользы из приложений Atlas, хорошиенавыки программирования клиентских сценариев абсолютно необходимы. Точка.

Тем не менее UpdatePanel и другие серверные элементы обеспечивают пре-восходный компромисс между необходимостью реализации асинхронной и вне-полосной функциональности и стремлением к использованию уже знакомойприкладной модели ASP.NET. Как было показано в этой главе, любая сущест-вующая страница ASP.NET легко преобразуется в страницу Atlas. Исходнаястраница делится на области, а с каждой областью разметки связывается свойэлемент UpdatePanel. Начиная с этого места каждая область обновляется отдель-но; при этом используются независимые и асинхронные вызовы, не влияющиена остальные части страницы. Текущая страница продолжает нормально работать,а области обновляются благодаря помощи среды Atlas. Такой режим называетсярежимом частичного обновления.

Page 110: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 4 Элементы MicrosoftASP.NET AJAX

В этой главе:I ASP.NET AJAX Control ToolkitI Элемент AccordionI Элемент Ratingi Элемент ReorderListi Серверные расширители Atlas

Хотя Atlas является прикладной средой, расширяющей возможности программиро-вания на стороне веб-клиента, он используется в основном серверными разра-ботчиками — скажем, разработчиками Microsoft ASP.NET или веб-разработчика-ми с высокой квалификацией в области серверного программирования. К сожа-лению, в настоящее время существует только один путь добавления новых воз-можностей и функциональности на стороне веб-клиента: это написание качест-венного код JavaScript.

Для этой цели Atlas предоставляет разработчикам три способа построенияширокофункциональных веб-приложений на базе серверо-центрической модели.Во-первых, разработчик может обновлять отдельные участки страниц, исполь-зуя частичное обновление вместо обычного возврата данных ASP.NET (см. гла-ву 3). Для создания таких областей используется специальный набор серверныхэлементов, среди которых центральное место занимает элемент UpdatePanel.

Помимо частичного обновления, разработчики могут использовать расши-рители элементов для добавления заранее определенных аспектов клиентскойстороны к новым и существующим элементам ASP.NET. Аспекты поведения (behaviors) реализуются в виде блоков JavaScript, наделяющие целевые элементыASP.NET новыми возможностями. Расширитель фактически представляет собойсерверный элемент, который генерирует сценарный код для расширения поведе-ния элемента ASP.NET на стороне клиента. Расширитель представляет общее по-ведение, а не специфическую функцию конкретного элемента; как следствие, онможет применяться к различным типам целевых элементов.

В комплект поставки Atlas входит набор готовых расширителей и аспектовповедения. Некоторые расширители входят в базовые сборки Atlas; для другихтребуется дополнительная сборка ASP.NET AJAX Control Toolkit (также называе-мая Atlas Control Toolkit или ACT). Тем не менее следует учесть, что в оконча-

Page 111: Microsoft ASP.NET 2.0 AJAX

ASP.NET AJAX Control Toolkit 1 1 1

тельной версии ситуация может измениться, и все расширители войдут в двоич-ные файлы Atlas. Наконец, если ни один из базовых расширителей не предос-тавляет нужной функции, вы всегда можете написать собственный расширительи определить новые аспекты поведения для серверных элементов.

Базовые и пользовательские расширители элементов ASP.NET позволяют ав-тору внедрить в клиентскую страницу новые аспекты поведения без написаниякода XML Script или JavaScript. В этой главе приводится краткий обзор характе-ристик, способов использования и реализаций расширителей элементов.

ASP.NET AJAX Control ToolkitКак уже говорилось выше, в настоящее время большинство расширителей эле-ментов откомпилировано в сборку, которая называется ASP.NET AJAX ControlToolkit или Atlas Control Toolkit (ACT). Эта сборка загружается отдельно и ре-гистрируется во всех приложениях, с которыми вы собираетесь ее использовать.Скорее всего, в будущем содержимое сборки будет интегрировано с базовымидвоичными файлами Atlas.

Рис. 4 . 1 . Пример веб-сайта, демонстрирующий возможности ACT

Page 112: Microsoft ASP.NET 2.0 AJAX

1 1 2 Глава 4. Элементы Microsoft ASP.NET AJAX

Настройка средыЧтобы загрузить новейшую версию ACT, посетите сайт http://atlas.asp.net и за-гляните в секцию Download. Инструментарий распространяется в виде файлаMicrosoft Windows Installer, поэтому после загрузки остается дважды щелкнутьна нем, чтобы установить компоненты ACT.

Проект ACTПосле завершения установки на жестком диске появляется проект Microsoft VisualStudio 2005 ASP.NET. Запустив проект, вы увидите страницу, показанную на рис. 4.1.

Ознакомившись с файлами проекта, вы увидите, что ACT представляет собойнабор элементов и расширителей Atlas, а также найдете многочисленные приме-ры, демонстрирующие их возможности. Кроме того, ACT содержит средства раз-работки, упрощающие создание и повторное использование ваших собственныхэлементов и расширителей. В пакет входят шаблоны Visual Studio 2005 дляMicrosoft Visual Basic и C#, а также библиотека вспомогательных классов, упро-щающих создание элементов и расширителей.

Добавление компонентов ACT на панель элементовИтак, ACT включает ряд элементов и расширителей, которые могут использо-ваться при создании страниц ASP.NET. Эти компоненты удобнее всего размес-тить на панели элементов (toolbox) Visual Studio 2005, чтобы разработчик мог легко выбрать нужный компонент и вставить его в текущую страницу. Чтобы до-бавить компонент ACT на панель элементов, сначала создайте на панели новуювкладку (щелкните правой кнопкой мыши на панели и выберите в контекстномменю команду Add Tab). После создания новой вкладке можно присвоить любоеимя — например, Atlas Control Toolkit. Затем вкладка заполняется всеми элемента-ми сборки ACT; для этого следует щелкнуть правой кнопкой мыши на панелиэлементов ниже созданной вкладки и выбрать команду Choose Items. На экранепоявляется стандартное диалоговое окно со сборками NET и компонентамиCOM. Откройте папку, в которую был установлен пакет ACT, и выберите сбор-ку AtlasControlToolkit из папки Bin папки SampleWebsite. Все! Когда это будет сде-лано, панель элементов будет выглядеть так, как показано на рис. 4.2.

ПРИМЕЧАНИЕВ этой главе я разделяю серверные элементы и расширители ACT. Строго говоря, чет-кого различия между ними не существует. В ACT входит ряд новых серверных элемен-тов (таких, как ReorderList) и гораздо большее количество расширителей — DragPanel,DropShadow и TextBoxWatermark.Чем элементы отличаются от расширителей? Элемент предоставляет замкнутый наборфункций и хорошо известное, фиксированное поведение, которое может настраиватьсятолько на уровне свойств и событий. Расширитель представляет поведение клиентскойстороны, которое может быть связано практически с любым элементом, для которогооно имеет смысл. Например, расширитель DropShadow можно связать как с кнопкой,так и с текстовым полем, и в обоих случаях целевой элемент будет воспроизводитьсяс отбрасываемой тенью. Несмотря на логические различия, серверные элементы и рас-ширители реализуются по одному принципу — в конечном счете, и те и другие являют-ся серверными элементами ASP.NET.

Page 113: Microsoft ASP.NET 2.0 AJAX

ASP.NET AJAX Control Toolkit 1 1 3

Рис. 4.2. Новая вкладка с компонентами ACT на панели элементов Visual Studio 2005

Регистрация компонентов ACT в страницеНесмотря на то что пакет ACT является «родной» частью прикладной среды Atlasи будет интегрирован в следующую версию платформы ASP.NET, на данныймомент это всего лишь внешняя библиотека. По этой причине пакет ACT необ-ходимо регистрировать в каждой без исключения странице, использующей какие-либо из его элементов или расширителей. Регистрация осуществляется директи-вой ©Register, как показано в следующем фрагменте:

<%$ Register Assembly="AtlasControlToolkit"Namespace="AtlasControlToolkit"TagPrefix="act" %>

Если вам не нравится дублирование одного фрагмента кода во всех страни-цах приложения, воспользуйтесь приемом, который использовался группой раз-работки ASP.NET для решения подобной проблемы с элементами Atlas.

Стоит заметить, что базовая библиотека Atlas фактически также является внеш-ней библиотекой для платформы ASP.NET, и поэтому для нее также необходима

Page 114: Microsoft ASP.NET 2.0 AJAX

1 1 4 Глава 4. Элементы Microsoft ASP.NET AJAX

явная регистрация на каждой странице. В ASP.NET 2.0 для включения директи-вы ©Register во все страницы приложения можно воспользоваться следующимконфигурационным сценарием:

<pages><controls>

<add namespace="Microsoft.Web.Ill"assembly="Microsoft.Web.Atlas"tagPrefix="atlas" />

<add namespace="Microsoft.Web.UI.Controls"assembly="Microsoft.Web.Atlas"tagPrefix="atlas"/>

</controls></pages>

Все элементы Microsoft.Web.UI и Microsoft.Web.UI.Controls автоматически ассо-циируются с префиксом atlas и не требуют явного включения директивы ©Registerво все страницы, в которых они используются. Для элементов ACT в файл Web.config также можно включить аналогичный блок кода:

<pages><controls>

<add namespace="AtlasControlToolkit"assembly="AtlasControlToolkit"tagPrefix="act"/>

</controls></pages>

Содержимое ASP.NET AJAX Control ToolkitACT — библиотека, предназначенная для расширения возможностей прикладнойсреды Atlas. Входящие в нее элементы могут измениться в будущем, их функ-циональность может быть расширена или урезана. На момент написания книгиACT содержит достаточно большой набор расширителей и элементов, хотя, ко-нечно, они не решают все возможные проблемы, возникающие при разработке.

Расширители в ACTВ табл. 4.1 перечислены расширители элементов из библиотеки ACT. Обратитевнимание: полное имя класса расширителя содержит суффикс Extender, кото-рый в таблице для краткости не указывается. Так, в сборке ACT нет компонентаCollapsiblePanel, но есть элемент CollapsiblePanelExtender и т. д.

Таблица 4.1. Расширители в ACT

Расширитель ОписаниеAlwaysVisibleControl Закрепляет элемент в углу страницы и сохраняет его

в «плавающем» положении над фоном страницы при прокруткеили изменении размеров страницы. Например, при помощиэтого расширителя можно обеспечить постоянное отображениепанели в левом верхнем углу страницы независимо от позициипрокрутки или размера окна браузера

Page 115: Microsoft ASP.NET 2.0 AJAX

ASP.NET AJAX Control Toolkit 1 1 5

Расширитель ОписаниеCascadingDropDown

CollapsiblePanel

ConfirmButton

DynamicPopulate

DragPanel

DropShadow

FilteredTextBox

HoverMenu

ModalPopup

NumericUpDown

Связывается с элементом DropDownList. Расширительавтоматически заполняет список данными, полученнымиот метода веб-службы. Он удобен при создании иерархийраскрывающихся списков, в которых расширитель автоматическизаполняет дочерние списки в зависимости от текущегосостояния выделения в предыдущих списках иерархии

Создает на веб-странице сворачиваемые секции. Расширительможет использоваться только с панельными элементами (то естьс элементом ASP.NET Panel или любого класса, производногоот него). Расширителю передается информация о том, какаяпанель страницы выполняет функции заголовка, а какаяпанель предоставляет содержимое для свертки

Связывается с кнопкой. Расширитель добавляет к событиюclick кнопки диалоговое окно подтверждения, реализованноена JavaScript. Расширитель поддерживается всеми классами,реализующими интерфейс IButtonControl, включая Button,LinkButton и ImageButton

Обновляет содержимое элемента результатом вызова методастраницы или веб-службы

Связывается с панелью. Расширитель реализует функциюперетаскивания и позволяет перемещать панель по странице.Разработчик задает перемещаемое содержимое, а такжеманипулятор, при нажатии которого активизируетсяоперация перетаскивания

Добавляет тень к любому элементу на странице. Расширительпозволяет задать степень прозрачности и ширину тени

Связывается с текстовым полем. Расширитель блокирует вводнедопустимых символов

Отображает содержимое ассоциированной панели, когдауказатель мыши задерживается над заданным элементом.Расширитель можно связать с любым элементом ASP.NET.В сущности, это специализированное и в высший степенигибкое средство реализации всплывающих подсказок

Связывается с элементом, способным инициироватьклиентское событие onclick (как правило, кнопкии гиперссылки). Расширитель реализует классическоемодальное диалоговое окно средствами HTML.Он отображает содержимое заданной панели, не позволяяпользователю взаимодействовать со страницей

Связывается с текстовым полем. Расширитель позволяетпереходить к следующему или предыдущему значению поля,щелкая на автоматически отображаемых кнопках.Поддерживается работа с числами, пользовательскимисписками и методами веб-служб

продолжение ■&

Page 116: Microsoft ASP.NET 2.0 AJAX

1 1 6 Глава 4. Элементы Microsoft ASP.NET AJAX

Таблица 4.1 (продолжение)

Расширитель ОписаниеPagingBulletedList

PasswordStrength

PopupControl

ResizableControl

RoundedCorners

TextBoxWatermark

ToggleButton

Связывается с элементами BulletedList. Расширитель группируетвсе элементы, связанные со списком, и упорядочивает ихв отсортированные страницы на стороне клиентаСвязывается с текстовым полем, предназначенным для вводапароля, и обеспечивает визуальную обратную связьПреобразует содержимое заданной панели во всплывающееокно без использования диалоговых окон HTML. Расширительможет быть связан с любым элементом, инициирующим любыеиз следующих событий клиентской стороны: onfocus, onclick,onkeydownСвязывается с любым элементом страницы. Позволяетизменять размеры элемента при помощи манипулятора,находящегося в правом нижнем углуДобавляет фоновую панель к любому элементу ASP.NET,в результате чего возникает иллюзия скругления угловисходного элемента. При этом общая высота исходногоэлемента слегка изменяетсяСвязывается с элементами TextBox. Расширитель помещаетв поле текст-подсказку, поясняющую, какие данные должнывводиться в этом поле (например, «Введите свое имя»). Подсказкаисчезает, как только пользователь начинает вводить текст,и снова появляется, когда текстовое поле остается пустымСвязывается с элементами CheckBox. Расширитель позволяетиспользовать нестандартные изображения при выводе флажков.Например, можно использовать разные изображения дляустановленных и сброшенных флажков

Как нетрудно предположить, для одних расширителей необходима специаль-ная поддержка со стороны браузера, а другие представляют собой обычныйфрагмент кода JavaScript, присоединенный к блоку элементов разметки. Помни-те, что все функции являются кросс-платформенными, хотя в сопроводительнойдокументации к выпуску ACT упоминается о возможных проблемах с браузеромSafari (из-за известных ошибок в его подсистеме разбора JavaScript). Для трехсамых популярных браузеров (Microsoft Internet Explorer, Firefox и Netscape)пока никаких проблем не выявлено. Мы вернемся к расширителям позднее, с при-мерами кода и более подробными описаниями.

Элементы ACTНаряду с расширителями, перечисленными в табл. 4.1, ACT также поддерживаетнесколько традиционных серверных элементов с расширенными возможностя-ми - Accordion, Rating и ReorderList.

Элемент Accordion позволяет создать несколько свертываемых панелей и ото-бражать только одну из них. Когда пользователь щелкает на новой панели, теку-щая панель сворачивается и освобождает место для вывода новой панели.

Page 117: Microsoft ASP.NET 2.0 AJAX

Элемент Accordion 1 1 7

Элемент Rating обеспечивает интуитивно понятный интерфейс для формиро-вания рейтинговых оценок, выраженных в количестве звездочек. Элемент пред-ставляет собой упакованную версию пользовательского интерфейса, используе-мого на некоторых веб-сайтах для оценки публикуемых материалов.

Элемент ReorderList ориентирован на работу с данными. Он позволяет из-менять порядок своих дочерних элементов посредством перетаскивания. Чтобыпереместить объект в списке, пользователь захватывает мышью его манипулятори перетаскивает в нужную позицию. В конце операции элемент выдает обраще-ние к серверу для сохранения нового состояния источника данных.

Сначала мы рассмотрим новые серверные элементы, а затем перейдем к рас-ширителям.

Элемент AccordionСвертываемые панели часто встречаются на многих современных, передовыхсайтах. На странице выводится короткий заголовок, а основной текст остаетсяскрытым и вызывается в случае необходимости. Расширитель CollapsiblePanel(см. далее) позволяет скрывать и отображать произвольные блоки разметки.Но что делать, если понадобилось создать иерархию панелей?

С помощью элемента Accordion можно сгруппировать несколько свертывае-мых панелей в один элемент и управлять состоянием каждой панели так, чтобыв любой момент времени могла быть развернута только одна панель.

Общие сведения об элементе AccordionЭлемент Accordion содержит коллекцию дочерних элементов AccordionPane, у ка-ждого из которых имеется свойство-шаблон для определения заголовка и содер-жимого. Каждая дочерняя панель может содержать произвольный код HTML,ASP.NET или Atlas.

Свойства элементаВ табл. 4.2 перечислены основные свойства элемента Accordion.

Таблица 4.2. Свойства элемента Accordion

Свойство ОписаниеAutoSize Значение свойства определяет способ определения элементом

своих фактических размеровContentCssClass Класс CSS, используемый для определения стилей содержимого

дочерних панелей (чтение и запись)FadeTransitions Свойство указывает, нужно ли использовать переходной эффект

растворения при свертке текущей панели. По умолчаниюиспользуется значение False

FramesPerSecond Частота смены кадров при анимации перехода к новой дочернейпанели. По умолчанию задается равной 30 кадрам в секунду

продолжение ■&

Page 118: Microsoft ASP.NET 2.0 AJAX

1 1 8 Глава 4. Элементы Microsoft ASP.NET AJAX

Таблица 4.2 (продолжение)

Свойство ОписаниеHeaderCssClass Класс CSS, используемый для определения стилей заголовков

дочерних панелей (чтение и запись)SelectedIndex Панель, развернутая в данный момент (чтение и запись)TransitionDuration Продолжительность переходной анимации в миллисекундах

(по умолчанию 250)

Как видите, элемент не обладает визуальными свойствами, кроме базовыхсвойств ASP.NET, определенных в родительском классе WebControl (BackColor,ForeColor и т. д.). В частности, у него нет стилевого свойства для дочерних пане-лей. Стили их заголовков и содержимого определяются классами CSS. Если быэлемент работал с использованием обычного возврата данных, то свойства клас-сов CSS, вероятно, были бы заменены объектами Style, как во многих классиче-ских элементах ASP.NET.

Анимация элементаЭлемент Accordion поддерживает анимацию в двух контекстах. При выборе но-вой панели содержимое текущей панели может «растворяться». Этот эффект неявляется обязательным, а его применение определяется логическим свойствомFadeTransitions. На небольших панелях он мало заметен. Анимация растворениятесно связана с переходной анимацией медленного развертывания содержимогоновой панели.

Второй формой анимации управляют свойства TransitionDuration и FramesPer-Second. Если отключить ее, эффект растворения действовать не будет, независи-мо от состояния свойства FadeTransitions.

Чтобы полностью отказаться от анимации и заменить ее быстрой сменой па-нелей, свойствам FramesPerSecond и TransitionDuration присваивается значение 0.В этом случае свойству FadeTransitions следует задать значение false, чтобы эле-мент не выполнял лишней работы, которая все равно не приведет к видимым ре-зультатам.

Изменение размера элементаРазмер элемента Accordion зависит как от элемента-контейнера, так и от содержи-мого разных панелей. Это означает, что общий размер элемента может изменять-ся при смене выбранной панели, в результате чего другие элементы страницымогут сдвигаться вверх или вниз. Свойство AutoSize помогает контролироватьобщий размер элемента Accordion.

Допустимые значения свойства объединены в перечисление AutoSize: None (ис-пользуется по умолчанию), Limit и Edit. Когда свойство AutoSize равно None, раз-меры элемента свободно изменяются в соответствии с размерами текущей панели.

При значении Limit элемент никогда не увеличивается сверх размеров, опре-деляемых свойствами Width и Height. Элемент Accordion наследует эти свойстваот базового класса. Если свойству AutoSize задано значение None, свойства Width

Page 119: Microsoft ASP.NET 2.0 AJAX

Элемент Accordion 1 1 9

и Height игнорируются. Если размеры содержимого превышают заданные разме-ры элемента, пользователь может полностью просмотреть его при помощи полоспрокрутки.

При значении Fill элемент всегда занимает прямоугольник, определяемыйсвойствами Width и Height; содержимое элемента разворачивается или прокручи-вается по мере необходимости. Развертывание содержимого всего лишь означаетувеличение дочерней панели.

Использование элемента AccordionЭлемент Accordion состоит из набора дочерних панелей, каждая из которых пред-ставляет собой экземпляр класса AccordionPane. Панели добавляются на уровнеразметки, а для программного получения коллекции панелей используется ме-тод GetAccordionPanes:

public IList<AccordionPane> GetAccordionPanesО

Расширенные возможности (такие, как программное определение панелейи управление видимостью) пока не реализованы.

Элемент Accordion в действииСледующий фрагмент кода демонстрирует использование элемента Accordion:

<div style="width:ЗООрх;"><act:Accordion ID="Accordionl" runat="server" Height="400px"

SelectedIndex="0"ContentCssClass="accordionContent"HeaderCssClass="accordionHeader"radeTransitions="true"AutoSize="Fill">

<act:AccordionPane ID="AccordionPanel" runat="server"><Header>One</Header><Content>This is the first pane</Content>

</act:AccordionPane><act:AccordionPane ID="AccordionPane2" runat="server">

<Header>Two</Header><Content>

<div style="height:400px">This is the second pane</div>

</Content></act:AccordionPane><act:AccordionPane ID="AccordionPane3" runat="server">

<Header>Three</Header><Content>This is the third pane</Content>

</act:AccordionPane><act:AccordionPane ID="AccordionPane4" runat="server">

<Header>Four</Header><Content>This is the fourth pane</Content>

</act:AccordionPane></act:Accordion>

</div>

Page 120: Microsoft ASP.NET 2.0 AJAX

1 2 0 Глава 4. Элементы Microsoft ASP.NET AJAX

Каждая свертываемая панель, включаемая в элемент Accordion, представленатегом <act:AccordionPane>. Определение панели состоит из шаблонов <header>и <content>.

В приведенном примере элемент Accordion встроен в тег <div> с фиксирован-ной шириной. Внешний контейнер определяет ширину и высоту элемента. Свой-ство AutoSize=Fill заставляет элемент заполнять весь ограничивающий прямо-угольник. Результат показан на рис. 4.3.

Рис. 4.3. Элемент Accordion в действии

Обратите внимание: содержимому второй панели назначена высота в 400 пик-селов, однако сам элемент Accordion не может быть выше 400 пикселов и не мо-жет бесконтрольно увеличиваться, потому что его размеры ограничены свойст-вом AutoSize. В результате для просмотра содержимого, не умещающегося в этихграницах, на второй панели отображается полоса прокрутки.

Page 121: Microsoft ASP.NET 2.0 AJAX

Элемент Rating 1 2 1

Панели элемента AccordionДочерняя панель элемента Accordion представляет собой простой веб-элементс именем AccordionPane. Свойство Header этого элемента используется для оп-ределения заголовка, то есть части панели, которая остается видимой послесвертывания. Стиль заголовка задается классом CSS, определяемым свойствомHeaderCssClass.

Аналогичным образом, содержимое панели определяется свойством Content,а его стиль — классом CSS, определяемым свойством ContentCssClass.

Элемент RatingИнтерес пользователей — один из ключевых факторов, определяющих успех веб-сайта. Но как его измерить? Многие сайты предлагают пользователям высказатьсвое мнение на специальных панелях, находящихся на страницах сайта. Для по-лучения информации от пользователей чаще всего применяется система рейтин-гов. Пользователю предлагается выбрать то количество звездочек, которым онбы оценил некоторый материал или функцию сайта.

Многие разработчики ASP.NET смогут легко реализовать схему рейтингов,работающую на основе классического возврата данных. Элемент Atlas Ratingобеспечивает стандартный механизм для работы с рейтингами на основе обрат-ных вызовов.

Общие сведения об элементе RatingВыходной код элемента состоит из повторяющегося тега <span>, оформлен-ного при помощи набора классов CSS. Каждый тег <span> представляет «звез-дочку» в системе рейтингов, а его стиль задается в соответствии с тем статусом,который он должен представлять. Рисунок 4.4 дает представление о внешнем видеэлемента Rating.

Рис. 4.4. Элемент Rating в действии

Page 122: Microsoft ASP.NET 2.0 AJAX

1 2 2 Глава 4. Элементы Microsoft ASP.NET AJAX

Свойства элементаВ табл. 4.3 перечислены важнейшие свойства элемента Rating.

Таблица 4.3. Свойства элемента Rating

Свойство ОписаниеCurrentRating Текущий рейтинг, представляемый элементом (по умолчанию

используется значение 3). Свойство доступно для чтения и записиEmptyStarCssClass Класс CSS для оформления «пустых» (не выбранных) звездочек.

Свойство доступно для чтения и записиFilledStarCssClass Класс CSS для оформления «заполненных» (выбранных)

звездочек. Свойство доступно для чтения и записиMaxRating Максимальный рейтинг, который может быть представлен

элементом (по умолчанию 5)RatingAlign Тип выравнивания звездочек (по умолчанию используется

горизонтальное выравнивание)RatingDirection Направление (ориентация) звездочек. По умолчанию при

горизонтальном выравнивании используется направление слеванаправо, а при вертикальном — сверху вниз

ReadOnly Свойство указывает, принимает ли элемент пользовательский вводStarCssClass Класс CSS, определяющий стиль всего элемента (чтение и запись)Tag Строка, которая передается серверному коду, обрабатывающему

щелчки на элементеWaitingStarCssClass Класс CSS, используемый при выводе «выбранных» звездочек

на время возврата данных сервером после изменения состоянияэлемента пользователем

Разметка, генерируемая элементом Rating, выглядит примерно так:<div id="Ratingl" style="float: 1 eft;">

<span id="Ratingl_Star_l" class="ratingStar filledRatingStar"style="f1 oat:1 eft;">&nbsp;</span>

<span id="Ratingl_Star_2" class="ratingStar filledRatingStar"style="f1 oat:1 eft;">&nbsp;</span>

</div>

Как видно из листинга, каждая «звездочка» обладает уникальным идентифи-катором и представляется тегом <span>, содержащим пустую строку. Однако изрис. 4.4 ясно видно, что звездочка представлена графическим изображением. Кактакое возможно?

Определение стиля элементаС элементом Rating ассоциируются четыре класса CSS. Класс StarCssClass оп-ределяет стиль всего элемента. Классы EmptyStarCssClass и FilledStarCssClassопределяют стиль тега <span>. Наконец, WaitingStarCssClass определяет стиль

Page 123: Microsoft ASP.NET 2.0 AJAX

Элемент Rating 1 2 3

заполненных звездочек в то время, пока элемент обращается с обратным вызо-вом к серверу (обычно заполненные звездочки выводятся желтым цветом, но навремя обновления они могут выводиться красным). Для заполнения можетиспользоваться графическое изображение или контрастный цвет фона. Возьмемследующие классы CSS:

.filledRatingStar{

background-color: #2E4d7B;}.emptyRatingStar{

background-image: url(images/NotSelected.png);}

Эффект от их применения показан на втором объекте на рис. 4.4. Выбраннаячасть ряда выводится в виде закрашенной полосы, а в остальной части элементарисуются пустые звездочки. Редактируя классы CSS, можно выбрать изображе-ния звездочек, соответствующие ожиданиям пользователей вашего приложения.

Использование элемента RatingЭлемент Rating относительно прост в использовании. Он не имеет дочерних эле-ментов или шаблонов, а разработчику достаточно задать значения несколькихсвойств (классы CSS).

Элемент Rating в действииСледующий код демонстрирует использование элемента Rating:

<h2>Rate this item:</h2><div>

<act:Rating ID="Ratingl" runat="server"CurrentRating="3"MaxRating="10"StarCssClass="ratingStar"WaitingStarCssClass="savedRatingStar"ri11edStarCssClass="fi11edRatingStar"EmptyStarCssClass="emptyRatingStar"OnChanged="Rating_Changed" />

</div>

Свойство MaxRating определяет максимальное количество звездочек. Первые(или последние, в зависимости от выбранного направления) CurrentRating звез-дочек в этом ряду оформляются с использованием стиля класса, имя которогозадается свойством FilledStarCssClass. Стили остальных звездочек определяютсяатрибутами класса, заданного свойством EmptyStarCssClass.

Очень важно, чтобы в свойствах элемента были заданы правильные именаклассов CSS. Скажем, если опустить стиль пустых звездочек, соответствующийтег <span> будет выведен без каких-либо графических изменений. Так как в ис-ходном варианте этот тег содержит пустую строку, визуальный вывод для негоне генерируется.

Page 124: Microsoft ASP.NET 2.0 AJAX

1 2 4 Глава 4. Элементы Microsoft ASP.NET AJAX

Модель событийЭлемент Rating внедряет в поток данных клиентского браузера фрагмент сценарно-го кода, который фактически решает две задачи: отслеживание перемещений мышив пределах ограничивающего прямоугольника элемента и обработка щелчков.

По мере того как пользователь перемещает мышь над пустыми звездочками,сценарный код автоматически переключает имя класса нижележащего тега <span>.

Чтобы изменить текущее значение рейтинга, достаточно щелкнуть на звез-дочке, соответствующей новому значению. Например, в рейтинговой системес пятью звездочками щелчок на четвертой звездочке устанавливает рейтинг 4.Когда это происходит, элемент Rating инициирует внеполосный вызов к серверуи выдает событие Changed:

protected void Rating_Changed(object sender, RatingEventArgs e){

// Выполнение содержательных действий на стороне сервера// (например, сохранение нового значения в базе данных)

}

Класс RatingEventArgs содержит три основных свойства — Tag, Value и Call-backResult. Свойство Tag передает произвольную строку от клиента серверу.Свойство Value обозначает текущее значение, выбранное в элементе. В свойствеCallbackResult передается любая дополнительная информация, которую сервервозвращает клиенту. Например, если событие Changed используется для сохра-нения рейтинга в базе данных, в строке CallbackResult может передаваться сооб-щение об ошибке в том случае, если при выполнении операции произошел сбой.

Элемент Reorder ListСодержимое баз данных, представленное в виде списка, часто выводится на веб-страницах. Обычно такие списки доступны только для чтения, то есть не могутнапрямую изменяться пользователем. Тем не менее в некоторых ситуациях мо-жет потребоваться переупорядочить содержимое списка. Представьте страницу,на которой пользователь выбирает несколько городов и получает информациюо текущей погоде. Города перечислены на странице в определенном порядке, нов какой-то момент пользователь захотел этот порядок изменить.

Конечно, разработчик может разместить на странице кнопку Move Up; чтобыв списке из 4 городов переместить последний город на первое место, придетсятрижды щелкнуть на кнопке. Такое решение легко программируется, но удоб-ным его не назовешь. Более естественно было бы дать пользователю возмож-ность выделить нужный город и перетащить его в нужное положение. Именноэту задачу и решает элемент ReorderList. Давайте познакомимся поближе с этимновым элементом ASP.NET Atlas.

Общие сведения об элементе ReorderListСодержимое элемента ReorderList задается серией шаблонов, описывающих струк-туру каждого объекта в списке, пользовательский интерфейс манипулятора пере-таскивания и пользовательский интерфейс точки вставки, в которую перемещается

Page 125: Microsoft ASP.NET 2.0 AJAX

Элемент ReorderList 1 2 5

перетаскиваемый объект. Впрочем , в программном интерфейсе элемента участ-вует ряд других свойств и событий .

Свойства элементаВ табл . 4.4 перечислены основные свойства элемента ReorderList. В частности ,в список включены свойства, значения которых могут задаваться атрибутами навеб -страницах ASP.NET. Элемент является производным от DataBoundControlи реализует интерфейс IRepeatlnfollser — типичный для элементов, поддерживаю-щих разнообразные варианты выравнивания и структуры (таких , как CheckBox-List). Базовый класс и интерфейс содержат ряд дополнительных свойств, относя-щихся к привязке данных и макету элемента .

Таблица 4.4. Свойства элемента ReorderList

Свойство Описание

AllowReorder

DataKeyField

DataSourceID

DragHandleAlignment

DragHandleTemplate

EditItemTemplate

EmptyListTemplate

InsertItemTemplate

ItemInsertLocation

ItemTemplate

ReorderTemplate

SortOrderField

Указывает, поддерживает ли элемент изменения порядкаобъектов перетаскиванием. Свойство автоматически задаетсяравным true при задании шаблона ReorderTemplate

Имя поля источника данных, выполняющего функциипервичного ключа

Идентификатор элемента-источника данных, используемогодля заполнения элемента ReorderList

Положение манипулятора относительно перетаскиваемогообъекта. Допустимые значения: Top, Left, Bottom и Right

Шаблон манипулятора, используемого для перетаскиванияи упорядочения содержимого списка

Шаблон, указывающий, что запись находится в режимередактирования

Шаблон списка, не содержащего данных

Шаблон, используемый для добавления новых объектов в список

Указывает позицию для размещения нового элемента, когдасвойство InsertItemTemplate используется для включения новогообъекта в список. Допустимые значения — Beginning и End

Шаблон для объектов списка

Шаблон, используемый для обозначения конечной позициипри перестановке элементов списка. Не связывается с данными

Поле, определяющее порядок сортировки объектов

Важнейшие свойства элемента — ItemTemplate, DragHandleTemplate и Reorder-Template. Свойство ItemTemplate позволяет заполнить список любыми даннымии макетом по вашему усмотрению . DragHandleTemplate определяет графическиеэлементы , необходимые пользователям для перетаскивания объектов списка .Наконец , ReorderTemplate определяет шаблон визуальной обратной связи , ото-бражаемый в ходе операции .

Page 126: Microsoft ASP.NET 2.0 AJAX

1 2 6 Глава 4. Элементы Microsoft ASP.NET AJAX

События элементаЭлемент ReorderList связывается с данными, а его расширенный пользователь-ский интерфейс в основном формируется из шаблонов. Это означает, что эле-мент может содержать любое количество дочерних элементов, способных ини-циировать возврат данных и изменять содержимое элемента.

Соответственно не приходится удивляться тому, что с элементом связывают-ся многочисленные события, перечисленные в табл. 4.5.

Таблица 4.5. События элемента ReorderList

Событие ОписаниеCancelCommand Происходит при щелчке на кнопке со свойством

CommandName=«Cancel» в пределах элементаDeleteCommand Происходит при щелчке на кнопке со свойством

CommandName=«Delete» в пределах элементаEditCommand Происходит при щелчке на кнопке со свойством

CommandName=«Edit» в пределах элементаInsertCommand Происходит при щелчке на кнопке со свойством

CommandName=«Insert» в пределах элементаItemCommand Происходит при щелчке на кнопке в шаблоне объектаItemCreated Происходит при создании объекта в спискеItemDataBound Происходит при связывании объекта списка с даннымиItemReorder Происходит при перемещении объекта в новую позицию

в конце операции переупорядочения спискаUpdateCommand Происходит при щелчке на кнопке со свойством

CommandName=«Update» в пределах элемента

Большинство командных событий относится к возможностям связанного ис-точника данных. Например, событие InsertCommand происходит в том случае, еслиэлемент ReorderList содержит шаблон с элементами для сохранения данных и вы-зывает команду Insert для связанного элемента-источника данных. Простой пример:

<act:ReorderList ...>

<InsertItemTemplate><div>

<asp:TextBox ID="TextBoxl" runat="server"Text='<^# BindC'Title") £>'></asp:TextBox>

<asp:LinkButton ID="LinkButtonl" runat="server"CommandName="Insert">Add</asp:LinkButton>

</div></InsertItemTemplate>

</act:ReorderList>

По щелчку на кнопке элемент ReorderList вызывает команду Insert для свя-занного источника данных (если он имеется). Новый объект со свойством Title

Page 127: Microsoft ASP.NET 2.0 AJAX

Элемент ReorderList 1 2 7

добавляется в начало или в конец источника данных в зависимости от значениясвойства ItemlnsertLocation.

Событие ItemReorder происходит на сервере перед отсылкой на сторону кли-ента нового элемента с новым порядком объектов. С событием передается струк-тура ReorderListltemReorderEventArgs:

public class ReorderListltemReorderEventArgs : EventArgs{

public ReorderListltem Item { get; set; }public int Newlndex { get; set; }public int Oldlndex { get; set; }

}

Свойство Item определяет перемещаемый объект, а свойства Newlndex и Old-Index — новую и старую позиции соответственно (индексы позиций начинаются с 0).

Использование элемента ReorderListРассмотрим простую страницу, на которой используется элемент ReorderList. Каквскоре будет показано, элемент ReorderList связывается с источником данныхи встраивается в элемент UpdatePanel.

Настройка элемента ReorderListВ следующем фрагменте представлен пример простого переупорядочиваемогосписка, связанного с элементом ObjectDataSource:

<act:ReorderList runat="server" ID="list"DataSourceID="ObjectDataSourcel"><ItemTemplate>

<asp:Label ID="Labell" runat="server"Text='<^# Eval("lastname") %>' />

</ItemTemplate><ReorderTemplate>

<asp:Panel ID="Panel2" runat="server" CssClass="reorderCue" /></ReorderTemplate>

</act:ReorderList><asp:ObjectDataSource ID="ObjectDataSourcel" runat="server"

TypeName="IntroAtlas.EmployeeManager"SelectMethod="LoadAl I">

</asp:ObjectDataSource>

В данном примере свойство DragHandleTemplate не задано; это означает, чтов его пользовательском интерфейсе отсутствует визуальный манипулятор дляперетаскивания. Содержимое элемента выглядит как маркированный список.Чтобы изменить порядок следования пунктов списка, пользователь щелкает и пе-ретаскивает текст рядом с маркером (рис. 4.5).

Из рисунка видно, что перемещаемый элемент отображается с применениемотдельного стиля. В общем случае при этом используется шаблон, заданныйсвойством ReorderTemplate, состоящий из текста объекта и каскадного стиля.Если шаблон отсутствует, но для списка разрешено переупорядочение (логиче-ское свойство AllowReorder), то в качестве визуального признака выполняемойоперации используется текст объекта, выведенный серым цветом.

Page 128: Microsoft ASP.NET 2.0 AJAX

1 2 8 Глава 4. Элементы Microsoft ASP.NET AJAX

Рис. 4.5. Перестановка содержимого в элементе ReorderList

Построить список с возможностью переупорядочения объектов совсем не-сложно. Тем не менее разработчик должен учесть пару важных аспектов.

Переупорядочение и события возврата данныхВ конце каждой операции перетаскивания элемент ReorderList производит воз-врат данных. Чтобы избежать полного обновления страницы, элемент ReorderListследует разместить в элементе UpdatePanel. Как объяснялось в главе 3, таким об-разом гарантируется обновление только пользовательского интерфейса списка(вместо полного обновления всей страницы). Задача решается несколькимистроками кода разметки:

<atlas:UpdatePanel runat="server" ID="UpdatePanell"><ContentTemplate>

<!-- Здесь размещается ReorderList -->

</ContentTemplate></atlas:UpdatePanel>

Почему элемент инициирует собственный возврат данных? ReorderList пыта-ется сохранить изменения, внесенные пользователем, чтобы при любом другомвозврате данных из страницы (скажем, вызванном щелчком на кнопке) поддер-живалось измененное состояние ReorderList, полученное в результате перетаски-вания. Любые изменения, вносимые на стороне клиента, должны сохраняться насервере; в противном случае они будут потеряны при первом же обновлениистраницы.

Page 129: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 2 9

Сохранение измененного порядкаЗапустив любую страницу с элементом ReorderList, вы заметите, что через не-сколько секунд после перетаскивания объекта в новую позицию он восстанавли-вается в исходной позиции. Почему это происходит? В конце операции перетас-кивания элемент ReorderList производит возврат данных, в результате на сервереинициируется событие ItemReorder, а список строится заново. Но список связанс данными, и если в процессе связывания ничего не изменилось, он будет связанс прежним набором записей, соответствующим старому порядку.

Соответственно, страница с элементом ReorderList должна обработать собы-тие ItemReorder и позаботиться о том, чтобы изменения на стороне клиента былиотражены в источнике данных, связанном с элементом. Событие ItemReorder об-ладает следующей сигнатурой:

void OnItemReorder(object sender, ReorderListltemReorderEventArgs e)

В обработчике события выполняется «реальная» работа по переупорядоче-нию, то есть объект перемещается из старой позиции в новую позицию, исполь-зуемую для заполнения списка. Реализация зависит от механизма связывания.Если был выбран вариант с элементом-источником данных (например, Object-DataSource), можно попробовать сортировку по полю, отражающему новый по-рядок. Если источник данных задается присваиванием объекта lEnumerable свой-ству DataSource, получите объект и внесите необходимые изменения. Например,для DataTable это означает перестановку двух записей.

ПРИМЕЧАНИЕЭлемент ReorderList может автоматически изменять порядок данных на стороне серве-ра, если у него задано свойство SortOrderField, а источник данных сортируется по ука-занному полю. Поле сортировки должно быть целочисленным.

Серверные расширители AtlasКроме полноценных серверных элементов вроде ReorderList и Accordion, ACTтакже включает подборку серверных элементов, предназначенных для расшире-ния существующих элементов страницы и наделения их новыми аспектамиповедения. Такие компоненты называются расширителями элементов (controlextenders) или просто расширителями.

Что такое расширитель?Расширитель представляет собой часть функциональности клиентской стороны,которую вы можете добавить к серверному элементу ASP.NET. Серверный эле-мент создает собственную разметку, а расширитель генерирует фрагмент кодаJavaScript, специально адаптированный для работы поверх элемента.

Расширитель представляет функциональность общего назначения, которая тео-ретически может совместно использоваться несколькими элементами ASP.NET.Классический пример — тень, отбрасываемая элементом. Фрагмент кода JavaScript

Page 130: Microsoft ASP.NET 2.0 AJAX

1 3 0 Глава 4. Элементы Microsoft ASP.NET AJAX

создает иллюзию тени для заданного элемента ASP.NET. Исходному элементуо выводе тени ничего не известно, но установленная на стадии выполнения связьмежду расширителем и элементом решает задачу.

Общие сведения об аспектах поведения AtlasРасширитель представляет собой серверную «обертку» для кода JavaScript, оп-ределяющего клиентский аспект поведения Atlas. Расширитель задает конфигу-рацию и генерирует код JavaScript, характеризующий требуемый аспект поведе-ния Atlas.

Аспект поведения Atlas представляет собой файл .js с определением функ-ции JavaScript. Функция может регистрировать обработчики для событий кли-ентской стороны и изменять DOM элементов разметки, с которыми она связана.Чтобы лучше понять цели и характеристики аспектов поведения Atlas, давай-те в общих чертах рассмотрим поведение, инкапсулированное в расширителеTextBoxWatermark.

Этот расширитель управляет выводом подсказки — справочного текста, кото-рый отображается в пустом текстовом поле. Подсказка автоматически удаляется,когда пользователь начинает вводить данные в поле, и не используется при от-правке данных. Если пользователь полностью удаляет текст из поля, подсказкаавтоматически восстанавливается.

В реализации подсказок задействованы три события HTML — onfocus, onblurи onkeypress. На стадии инициализации аспект поведения подсказки также зада-ет новый стиль и текст по умолчанию для целевого текстового поля, если ононе содержит данных. Когда текстовое поле получает фокус ввода, обработчиксобытия удаляет текст подсказки и восстанавливает исходный стиль. Во времяввода данных обработчик onkeypress обеспечивает вывод подсказки в случаенеобходимости. Наконец, когда текстовое поле теряет фокус (событие onblur),обработчик возвращает подсказку, если содержимое поля представляет собойпустую строку.

Чтобы связать это поведение с элементом ASP.NET ТехШох, вам потребуетсярасширитель. Впрочем, для специалистов по XML Script и JavaScript существуетальтернативный вариант — для достижения тех же результатов можно написатьфрагмент клиентского кода.

ПРИМЕЧАНИЕКонцепция аспектов поведения Atlas близка к концепции аспектов поведения DHTML(Dynamic HTML). Аспекты DHTML, впервые появившиеся в Internet Explorer, пред-ставляли собой сценарный файл (или откомпилированный объект COM), которыйобрабатывал события HTML и модифицировал DOM тега HTML для реализациижелаемого поведения. Аспекты поведения DHTML использовались для расширениявозможностей отдельных тегов HTML. Аспекты поведения Atlas действуют более уни-версально: они расширяют возможности блока разметки, сгенерированного отдельнымэлементом ASP.NET, который может содержать один или несколько тегов HTML.Кроме того, расширитель Atlas не ограничивается Internet Explorer и работает в раз-ных браузерах.

Page 131: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 3 1

Целевые свойстваРасширители обладают набором свойств для настройки поведения. Класс рас-ширителя наследует от обобщенного класса с именем ExtenderControlBase:

public class TextBoxWatermarkExtender :ExtenderControlBase<TextBoxWatermarkProperties, TextBox>

{

}

Класс расширителя должен получать «извне» два ключевых параметра: кол-лекцию используемых свойств (целевые свойства) и класс элемента, к которомуон применяется. В следующем примере класс TextBoxWatermarkProperties предо-ставляется системой и группирует все свойства, используемые при расширениифункциональности целевого элемента. Класс, представляющий целевые свойст-ва, включает общее свойство с именем TargetControllD. Свойство определяет эле-мент страницы, к которому применяется расширитель с заданной конфигурацией.

Как правило, на странице размещается один расширитель определенного типа,снабженный одним или несколькими наборами свойств — по одному для каждо-го целевого элемента, как в следующем примере:

<act:TextBoxWatermarkExtender ID="Watermarkl" runat="server"><act:TextBoxWatermarkProperties TargetControlID="TextBoxl"

WatermarkText=" ... " WatermarkCssClass=" ... " />

<act:TextBoxWatermarkProperties TargetControlID="TextBox2"WatermarkText=" ... " WatermarkCssClass=" ... " />

</act:TextBoxWatermarkExtender>

Вооружившись этой информацией, перейдем к описанию программного ин-терфейса расширителей ACT и базовых библиотек Atlas. Расширители будутсгруппированы в соответствии с возможностями их целевых элементов.

Привязка данныхСвойства компонентов-расширителей также могут инициализироваться посред-ством декларативной привязки данных, по аналогии со свойствами классическихсерверных элементов ASP.NET.

<act:TextBoxWatermarkExtender ID="Watermarkl" runat="server"><act:TextBoxWatermarkProperties

TargetControlID="TextBoxl"WatermarkText='<^# Eval("SomeColumn") %>' />

</actToolkit:TextBoxWatermarkExtender>

В этом фрагменте продемонстрировано заполнение свойства WatermarkTextрасширителя TextBoxWatermark содержимым заданного столбца в связанном ис-точнике данных. Для выполнения привязки используется метод Eval. Но что-бы этот способ работал, целевой элемент — текстовое поле TextBoxl в данномслучае — должен быть встроен в контейнер, связанный с источником данных.

Page 132: Microsoft ASP.NET 2.0 AJAX

1 3 2 Глава 4. Элементы Microsoft ASP.NET AJAX

Например, декларативная привязка будет работать при использовании расши-ренного элемента внутри шаблона.

ПРИМЕЧАНИЕК числу интересных особенностей расширителей относится управление клиентскимсостоянием. Чем больше сложных и интерактивных функций реализуется на сторонеклиента, тем внимательнее нужно следить за тем, чтобы действия пользователя небыли потеряны при полном обновлении страницы посредством классического возвра-та данных ASP.NET.Не забывайте, что страницы Atlas, прежде всего, являются страницами ASP.NET;следовательно, они могут содержать обычные кнопки отправки, которые инициируютвозврат данных (такие же, как в любой классической странице, никак не связаннойс Atlas). При обработке возврата элементы генерируются на полученной странице с уче-том их текущего состояния. По этой причине некоторые расширители сохраняют кри-тическую информацию состояния на стороне клиента так, чтобы эта информация нетерялась между обновлениями. Информация сохраняется в строке, называемой клиент-ским состоянием, а для ее хранения используется скрытое поле. Получение и сохране-ние клиентского состояния осуществляется через интерфейс JavaScript. В классахцелевых свойств также существует серверный программный интерфейс для чтенияклиентского состояния. Например, элемент Accordion использует строку клиентскогосостояния для хранения индекса текущей панели. Клиентское состояние не отражает-ся на использовании элементов и расширителей ACT, но о нем необходимо знать принаписании пользовательских элементов и расширителей.

Расширители панелейНа страницах ASP.NET часто встречаются блоки разметки, которые пользовате-ли могут перемещать, сворачивать или разворачивать по мере надобности. Сле-довательно, идеальный панельный элемент ASP.NET должен поддерживать какперетаскивание, так и свертку. Специально для этой цели в Atlas определены двасерверных аспекта поведения, которые позволяют легко создавать сворачивае-мые секции и перетаскивать панели по странице.

Расширитель DragPanelРасширитель DragPanel принадлежит к числу простейших расширителей Atlas.Он обладает всего двумя целевыми свойствами; первое определяет перетаски-ваемую панель, а второе — панель, которая должна использоваться в качествеманипулятора перетаскивания:

<act:DragPanelExtender ID="DragPanelExtenderl" runat="server"><act:DragPanelProperties

TargetControlID="CustomerPanel"DragHandleID="CustomersDragHandle" />

</act:DragPanelExtender>

Как подсказывает само имя, свойство TargetControllD определяет идентифика-тор перемещаемого панельного элемента страницы. С другой стороны, свойствоDragHandlelD определяет идентификатор панельного элемента, используемогов качестве манипулятора перетаскивания. Другими словами, чтобы перетащить

Page 133: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 3 3

целевую панель, пользователь захватывает и перетаскивает панель-манипулятор.Несмотря на функциональные различия, эти две панели логически связаны и ге-нерируются с использованием вложенных тегов:

<asp:Panel ID="CustomersPanel" runat="server" > <asp:Panel ID="CustomersDragHandle" runat="server">

<div style="background-color:yellow">Customers</div></asp:Panel><asp:Panel runat="server">

<asp:gridview runat="server" DataSourceID="ObjectDataSource1"><Columns>

…</Columns>

</asp:gridview><asp:ObjectDataSource ID="ObjectDataSource2" runat="server"

TypeName="IntroAtlas.CustomerManager"SelectMethod="LoadAll">

</asp:ObjectDataSource></asp:Panel>

</asp:Panel>

Целевая панель обычно содержит панель манипулятора как дочерний элемент.Таким образом достигается эффект перемещения всей панели так, как если быона была традиционным окном Microsoft Windows (рис. 4.6).

Рис. 4.6. Расширитель DragPanel в действии

Расширитель CollapsiblePanelРасширитель создает на странице сворачиваемую секцию, объединяя две пане-ли — панель содержимого и контроллер сворачивания. В простейшей форме рас-ширитель CollapsiblePanel выглядит примерно так:

<act:CollapsiblePanelExtender ID="CollPanel" runat="server"><act:Col IapsiЫ ePanelProperties

TargetControlID="ContentPanel"

Page 134: Microsoft ASP.NET 2.0 AJAX

1 3 4 Глава 4. Элементы Microsoft ASP.NET AJAX

ExpandControlID="HeaderPanel"CollapseControlID="HeaderPanel"

</act:Col 1apsi Ы ePanelExtenders

Как обычно, свойство TargetControllD задает целевую панель. Свойства Expand-ControllD и CollapseControllD задают панели, используемые при развертыванииили свертывании панели содержимого. Обратите внимание на исключительнуюгибкость архитектуры компонента — она позволяет использовать разные панелидля управления развертыванием и свертыванием панели содержимого. Вероятно,на практике вы будете обычно использовать одну панель заголовка с графиче-ской кнопкой, изменяющейся в соответствии с состоянием панели содержимого.В следующем фрагменте кода представлен более полный пример использованиярасширителя:

<act:CollapsiblePanelExtender ID="cpe" runat="server"><act:Col 1apsi Ы ePanelProperties

TargetControlID="Col1apsi Ы eCustomersPanelContent"ExpandControlID="Col1apsi Ы eCustomersPanel"CollapseControlID="CollapsibleCustomersPanel"Collapsed="true"ExpandDirection="Vertical"ImageControlID="ToggleImage"Expandedlmage="~/images/collapse.jpg"ExpandedText="Col1 apse"Collapsedlmage="~/images/expand.jpg"CollapsedText="Expand" />

</act:Col 1apsi Ы ePanelExtender>

Необязательное свойство ImageControllD определяет элемент Image, щелчокна котором приводит к сворачиванию или разворачиванию панели. СвойстваExpandedlmage и Collapsedlmage задают URL изображений, используемых дляразворачивания и сворачивания. Свойства CollapsedText и ExpandedText задаюттекст всплывающих подсказок для изображений. Свойство Collapsed задает состоя-ние панели, а свойство ExpandDirection — направление разворачивания (горизон-тальное или вертикальное). На рис. 4.7 показано, как выглядит элемент в действии.

В следующем примере продемонстрировано использование типичной парыэлементов Panel с расширителем:

<asp:Panel ID="CollapsibleCustomersPanel" runat="server"><asp:Image ID="ToggleImage" runat="server"

Imagellrl="-7 images/collapse.jpg" /><t»Customers</t»

</asp:Panel><asp:Panel ID="Col1apsibleCustomersPanelContent" runat="server"

Height="0" CssClass="collapsePanel">

</asp:Panel>

В отличие от перетаскиваемых панелей, панели заголовка и содержимого яв-ляются раздельными и обычно следуют друг за другом в разметке страницы.При возврате данных клиентом панель расширителя автоматически сохраняети восстанавливает клиентское состояние свертывания/развертывания.

Page 135: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 3 5

Рис. 4.7. Расширитель CollapsiblePanel в действии

ПРИМЕЧАНИЕ

Чтобы избежать мерцания при отображении сворачиваемой панели, проследите за тем,чтобы для нее были правильно определены стили. Свойство Height должно быть рав-но 0, а стиль CSS overflow должен быть равен hidden.

Расширители кнопокНесомненно, кнопки принадлежат к числу самых распространенных элементовстраниц ASP.NET. Но по мере расширения функциональности страниц возника-ет потребность в дополнительных функциях кнопок, чтобы кнопки не отставалиот ожиданий пользователя. В Atlas входят два расширителя, применяемых к кноп-кам отправки данных и псевдокнопкам, образующим элемент CheckBox.

Расширитель ConfirmButtonКогда пользователь щелкает на кнопке, иногда бывает безопаснее запросить у негоподтверждения на выполнение операции. В стандартном варианте реализацииэтого поведения с кнопкой на странице ASP.NET связывается сценарный код,который вызывает диалоговое окно JavaScript с подтверждающим сообщением.Расширитель ConfirmButton значительно упрощает эту стандартную задачу и по-зволяет решать ее на декларативном уровне:

<asp:Button runat="server" ID="Buttonl" Text="Click me" /><act:ConfirmButtonExtender ID="cbe" runat="server">

<act:ConfirrnButtonProperties

Page 136: Microsoft ASP.NET 2.0 AJAX

1 3 6 Глава 4. Элементы Microsoft ASP.NET AJAX

TargetControlID="Button1"ConfirmText="Are you sure you want to click this?" />

</act:ConfirmButtonExtender>

Свойство ConfirmText определяет текст в окне сообщения, выводимом прищелчке на кнопке. Форматные теги (такие, как <Ь> и <i>) запрещены, но в тек-сте могут использоваться примитивы HTML. Например, конструкция &#10 по-зволяет прервать текущую строку и продолжить сообщение в следующей строкевывода. Запрет на использование форматных тегов обусловлен кодом JavaScriptэлемента ConfirmButton — в нем задействован вызов JavaScript window.confirm, по-этому форматирование HTML не имеет смысла (диалоговое окно подтвержде-ния создается функцией Windows MessageBox, не поддерживающей HTML).

Во внутренней реализации расширитель ConfirmButton назначает обработ-чик для события onsubmit формы и поглощает событие, если пользователь неподтвердит операцию. Расширитель может использоваться только с элемента-ми, реализующими интерфейс IButtonControl, в том числе с элементами LinkButtonи ImageButton.

Расширитель ToggleButtonФлажки (check boxes) представляют собой графические элементы HTML, обычнопредставленные парой небольших графических изображений (для установлен-ного и сброшенного состояния) и сопроводительным текстом. Каждый браузерможет использовать свою пару изображений, в результате чего флажки слегкаразличаются по внешнему виду.

Расширитель ToggleButton имитирует флажки с применением нестандартныхизображений. Он применяется к элементу CheckBox и заменяет его совершенноновым блоком разметки, использующим пользовательскую графику и обладаю-щим таким же поведением, что и стандартный флажок:

<act:ToggleButtonExtender ID="ToggleButtonExtenderl"runat="server"><act:ToggleButtonProperties

TargetControlID="CheckBoxl"ImageWidth="19"ImageHeight="19"UncheckedImagellrVDontLike.gif"CheckedImageUrl="Like.gif" />

</act:ToggleButtonExtender>

Свойства ImageWidth и ImageHeight определяют желательный размер изобра-жений. Учтите, что эти атрибуты являются обязательными. Свойства Unchecked-ImageUrl и CheckedlmageUrl задают изображения, используемые соответственнодля сброшенного и установленного состояния.

Расширители временных оконПрактически любой веб-разработчик имеет собственную точку зрения по поводувременных окон (popup windows). Нельзя отрицать, что временные окна — осо-бенно модальные диалоговые окна — значительно упрощают выполнение многих

Page 137: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 3 7

задач. К их недостаткам можно отнести то, что временные окна HTML являют-ся браузерными окнами и требуют создания страницы. Расширители временныхокон, предоставляемые Atlas, не требуют создания нового экземпляра браузера,а их работа сводится к отображению содержимого заданной вами панели (в мо-дальном или немодальном режиме).

Расширитель ModalPopupРасширитель ModalPopup отображает в модальном режиме все содержимое, свя-занное с элементом, определяемым свойством PopupControllD. В этом случаесвойство TargetControllD ссылается на элемент с поддержкой щелчков:

<act:ModalPopupExtender ID="mpe" runat="server"><act:ModalPopupProperties

TargetControlID="LinkButtonl"PopupControlID="PopupContent"OkControlID="Buttonl"CancelControlID="Button2">

</act:ModalPopupExtender>

Расширитель ModalPopup активизируется по событию onclick целевого элемен-та. Таким образом, в качестве целевого может выступать только элемент, поддер-живающий щелчки мышью. Элемент PopupControllD не обязан быть панелью;в общем случае он может быть каким угодно элементом. Тем не менее обычнодля отображения во временных окнах используются контейнеры, содержащиедругие элементы — чаще всего Panel.

На панели временного окна необходимо идентифицировать элементы, выпол-няющие две операции: подтверждения и отмены. Идентификаторы таких элемен-тов (как правило, кнопки) задаются свойствами OkControllD и CancelControllD.Естественно, открытие временного окна является действием клиентской сторо-ны, поэтому щелчки на элементе подтверждения или отмены должны обрабаты-ваться кодом JavaScript. Свойство OnOkScript задает функцию JavaScript, запус-каемую при щелчке на кнопке подтверждения; при щелчке на кнопке отменызапускается функция, определяемая свойством OnCancelScript.

Следующая разметка демонстрирует фрагмент типичной модальной панели.Обратите внимание: элемент Panel должен задать свой атрибут CSS display рав-ным попе, чтобы все его содержимое сначала оставалось невидимым.

<asp:LinkButton ID="LinkButtonl" runat="server" text="Click me" /><asp:Panel runat="server" ID="PopupContent" BackColor="Yellow">

<div style="margin:10px">Take note of this message and tell us if you strongly agree.<br /><br /><asp:Button ID="Buttonl" runat="server" Text="Yes" width="40px" /><asp:Button ID="Button2" runat="server" Text="No" width="40px" /></div>

</asp:Panel>

На рис. 4.8 показано модальное диалоговое окно в действии.

Page 138: Microsoft ASP.NET 2.0 AJAX

1 3 8 Глава 4. Элементы Microsoft ASP.NET AJAX

Рис. 4.8. Расширитель ModalPopup в действии

Расширитель дополняется парой графических свойств: DropShadow и Васк-groundCssClass. Логическое свойство DropShadow указывает, нужно ли имитиро-вать тень от временного окна, как на рис. 4.8. Свойство BackgroundCssClass опре-деляет стиль, временно применяемый к базовой странице:

modalBackground {background-color:Gray;filter:alpha(opacity=70);opacity:0.7;

}

Этот стиль окрашивает страницу в серый цвет и слегка затушевывает ее дляпущего эффекта.

Расширитель PopupControlРасширитель PopupControl можно связать с любым элементом HTML, генери-рующим события onclick, onfocus или onkeydown. Конечной целью расширителяявляется отображение временного окна с дополнительной информацией — на-пример, календарем или текстовым полем, в котором пользователь должен вве-сти дату. Содержимое панели представляется элементом Panel и может включатьсерверные элементы ASP.NET, статический текст и элементы HTML:

<asp:textbox runat="server" ID="InvoiceDateTextBox" /><asp:panel runat="server" ID="Panel1">

<asp:Calendar ID="Calendarl" runat="server">

Page 139: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 3 9

</asp:Calendars</asp:panel>

<act:PopupControlExtender ID="PopupExtenderl" runat="server"><act:PopupControlProperties

TargetControlID="InvoiceDateTextBox"PopupControlID="Panel1"Position="Bottom" />

</act:PopupControlExtender>

Свойство TargetControllD указывает на элемент, открывший временное окно,тогда как PopupControllD указывает на панель с отображаемыми элементами.Свойство Position задает позицию панели — сверху, слева, справа или снизу отродительского элемента (рис. 4.9).

Рис. 4.9. Расширитель PopupControl в действии

Дополнительные свойства OffsetX и OffsetY обозначают смещение временногоокна от выбранной позиции в пикселах.

Обычно временное окно содержит интерактивные элементы и выполняетвозврат данных. По этой причине содержимое временного окна можно вставитьв элемент UpdatePanel, чтобы оно могло выполнять серверные операции без об-новления всей страницы. Как правило, временное окно закрывается после воз-врата данных — например, окно на рис. 4.9 настроено таким образом, что оно за-кроется после выбора даты пользователем. При этом календарь генерирует насервере событие SelectionChanged.

protected void Calendarl_SelectionChanged(object sender, EventArgs e){

PopupExtenderl.Commit(Calendarl.SelectedDate.ToShortDateString());

Page 140: Microsoft ASP.NET 2.0 AJAX

1 4 0 Глава 4. Элементы Microsoft ASP.NET AJAX

Метод Commit присваивает указанное значение свойству по умолчанию ассо-циированного элемента. Если вы хотите управлять тем, какому свойству (отлич-ному от свойства по умолчанию) должно присваиваться значение при закрытиивременного окна, воспользуйтесь свойством CommitProperty. Свойство Commit-Script определяет функцию JavaScript, выполняемую на стороне клиента послеприсваивания результата.

ПРИМЕЧАНИЕПомните, что при использовании элемента UpdatePanel в элементе ScriptManager дол-жен быть включен режим частичного обновления (EnablePartialRendering). В против-ном случае при выборе пользователем даты в календаре будет выполняться полныйвозврат данных, сопровождающийся мерцанием страницы. Что еще хуже, из текстово-го поля исчезнет выбранная дата, и в нем восстановится исходное содержимое (в на-шем примере это пустая строка).

Расширители пользовательского интерфейсаСамую многочисленную группу расширителей Atlas составляют расширителипользовательского интерфейса — то есть специальные компоненты, упрощаю-щие реализацию расширенных функций для удобства пользователя.

Расширитель HoverMenuРасширитель HoverMenu, как и PopupControl, может связываться с любым эле-ментом ASP.NET. Оба расширителя отображают временную панель с дополни-тельным содержимым, но активизируются по разным событиям. HoverMenu ото-бражает свою панель тогда, когда пользователь задерживает указатель мыши надцелевым элементом. Панель отображается в позиции, заданной разработчиком:слева, справа, снизу или сверху от целевого элемента. При этом элементу можноназначить дополнительный стиль CSS, обеспечивающий его визуальное выделе-ние (рис. 4.10).

Расширитель HoverMenu хорошо подходит для реализации автоматическиотображаемых контекстных меню для практически любых элементов ASP.NET,а также для вывода рекомендаций по заполнению некоторых полей. Например,когда на рис. 4.10 пользователь задерживает указатель мыши над текстовым по-лем, появляется список рекомендуемых значений, упрощающих ввод.

<asp:TextBox ID="TextBoxl" runat="server" />

<asp:Panel ID="Panel1" runat="server" CssClass="popupMenu"><asp:RadioButtonList ID="RadioButtonListl" runat="server"

AutoPostBack="true"OnSelectedIndexChanged="RadioButtonListl_SelectedIndexChanged"><asp:ListItem Text="Dino Esposito"></asp:ListItem><asp:ListItem Text="Nancy Davolio"></asp:ListItem><asp:ListItem Text="Andrew Fuller"></asp:ListItem><asp:ListItem Value="" Text="None of the above"></asp:ListItem>

</asp:RadioButtonList></asp:Panel>

Page 141: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 4 1

<act:HoverMenuExtender ID="HoverMenul" runat="server"><act:HoverMenuProperties TargetControlID="TextBoxl"

HoverCssClass="hoverPopupMenu"PopupControlID="Panel1"PopupPosition="Right" />

</act:HoverMenuExtender>

Рис. 4.10. Расширитель HoverMenu в действии

Элемент Panel 1 определяет список переключателей с рекомендуемыми вари-антами заполнения текстового поля. Расширитель HoverMenu связывается с це-левым текстовым полем и определяет Panel 1 как динамическую панель для вре-менного отображения информации. Свойство PopupPosition определяет позициюпанели по отношению к целевому элементу. Другие свойства (такие, как OffsetXи OffsetY) определяют смещение панели. Свойство PopDelay определяет задержку(в миллисекундах) между остановкой указателя мыши и появлением панели.

Page 142: Microsoft ASP.NET 2.0 AJAX

1 4 2 Глава 4. Элементы Microsoft ASP.NET AJAX

Необязательное свойство HoverCssClass изменяет стиль текстового поля при появ-лении меню подсказки. Интересно взглянуть на класс CSS, связанный с панелью:

.popupMenu{

position:absolute;visibility:hidden;

background-color:#F5F7F8;}.hoverPopupMenu{

background-color:yellow;}

Очень важно, чтобы атрибут visibility панели был установлен равным hidden;в противном случае панель появится при загрузке страницы и будет скрыта впо-следствии.

Как и в случае с расширителем PopupControl, для полноценного использова-ния расширителя HoverMenu необходимо разместить расширенные элементывнутри элемента UpdatePanel. Предыдущий фрагмент разметки вставляется в тегContentTemplate следующего определения элемента UpdatePanel:

<atlas:UpdatePanel ID="UpdatePanell" runat="server"Mode="Conditional">

<ContentTemplate>

</ContentTemplate><Triggers>

<atlas:ControlEventTrigger ControlID="RadioButtonListl"EventName="SelectedIndexChanged" />

</Triggers></atlas:UpdatePanel>

Когда пользователь щелкает на переключателе, панель производит асинхрон-ный возврат данных и генерирует на сервере событие SelectedlndexChanged:

void RadioButtonListl_SelectedIndexChanged(object sender, EventArgs e){

TextBoxl.Text = RadioButtonListl.SelectedValue;}

Серверный обработчик события обновляет содержимое текстового поля, какпоказано на рис. 4.10.

Расширитель DropShadowРасширитель DropShadow имитирует эффект тени от элементов-панелей, чтопридает им более профессиональный вид. Степень прозрачности и ширина тенизадаются свойствами элемента:

<asp:Panel runat="server" ID="Panel1"><div style="padding:8px">

<asp:TextBox ID="TextBoxl" runat="server" /></div>

</asp:Panel>

Page 143: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 4 3

<act:DropShadowExtender ID="DropShadowExtenderl" runat="server"><act:DropShadowProperties TargetControlID="Panell"

Opacity=".65" Width="5" Rounded="true" /></act:DropShadowExtender>

Свойство TargetControllD задает элемент, снабжаемый тенью. Как правило, имявляется элемент Panel; впрочем, тень может применяться к любому элементуASP.NET — например, TextBox (при условии, что при этом не используется за-кругление углов). Степень прозрачности тени регулируется свойством Opacity,принимающим значения из диапазона от 0 до 1 (0 означает полную прозрач-ность). Чем ближе значение к 1, тем темнее будет тень.

Логическое свойство Rounded указывает, должна ли панель и прилегающаяк ней тень иметь закругленные края. По умолчанию используется значение false.На рис. 4.11 показан расширитель DropShadow в действии.

Рис. 4.11. Расширитель DropShadow в действии

Расширитель RoundedCornersРасширитель RoundedCorners является частным случаем расширителя DropShadow,так как его функциональность ограничивается закруглением углов дочерних па-нелей:

<asp:Panel runat="server" ID="Panel1" BackColor="LightBlue" Width="170px"><div style="margin-left:2px">

<asp:TextBox ID="TextBoxl" runat="server"BackColor="LightBlue"BorderWidth="Opx" />

</div></asp:Panel><act:RoundedCornersExtender ID="RoundedCornerExtenderl" runat="server">

<act:RoundedCornersProperties TargetControlID="Panell" Radius="6"Color="LightBlue" />

</act:RoundedCornersExtender>

Аргументы задают целевой элемент, радиус закругления и цвет границы.Закругленные углы создаются рисованием дополнительной границы вокруг

Page 144: Microsoft ASP.NET 2.0 AJAX

1 4 4 Глава 4. Элементы Microsoft ASP.NET AJAX

целевого элемента. Если удалить все границы вокруг текстового поля и ис-пользовать одинаковые цвета фона для панели и текстового поля, можно со-здать симпатичный эффект, показанный на рис. 4.12, — закругленное текстовоеполе.

Рис. 4.12. Расширитель RoundedCorners в действии

Расширитель AlwaysVisibleControlРасширитель AlwaysVisibleControl закрепляет элемент (или панель с элементами)у одного из углов страницы, чтобы при прокрутке или изменении размеров стра-ницы элемент «плавал» над фоном. Он может использоваться практически с лю-бым элементом ASP.NET.

<span style="background-color:yellow;" runat="server" id="Msg">Need a bit of dummy text? Look at<b>http://www.loremipsum.net</b></span>

<act:AlwaysVisibleControlExtender ID="avl" runat="server"><act:AlwaysVisi Ы eControlProperties

TargetControlID="Msg"HorizontalSide="Left"VerticalSide="Top" />

</act:AlwaysVisi Ы eControlExtender>

Свойства HorizontalSide и VerticalSide определяют угол страницы, в которомзакрепляется целевой элемент. Свойство HorizontalSide принимает допустимыезначения Left и Right, а свойство VerticalSide — Тор и Bottom. Смещение от каждо-го из краев определяется свойствами VerticalOffset и HorizontalOffset. Наконец,свойство ScrollEffectDuration указывает продолжительность эффекта прокруткипри перемещении целевого элемента (в секундах) — рис. 4.13.

Учтите, что расширитель не может применяться к простым элементам HTML.Если потребуется обеспечить постоянную видимость блока HTML (например,тега <span> из предыдущего примера), добавьте атрибут runat="server" и присвой-те уникальный идентификатор.

Page 145: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 4 5

Рис. 4.13. Расширитель AlwaysVisibleControl в действии

ПРИМЕЧАНИЕПри тестировании некоторых элементов, рассматривавшихся до настоящего момента,возможно мерцание экрана и перемещение элементов при загрузке страницы. Чтобыэтого не происходило, перед подключением расширителя разместите целевые элемен-ты в нужных позициях при помощи элемента CSS position.

Расширитель DragOverlayВ отличие от других расширителей, рассмотренных ранее, DragOverlay не опреде-ляется в ACT. Он реализуется в базовой библиотеке Atlas, а для его работы не-обходим префикс <atlas>. Расширитель переводит один или несколько сервер-ных элементов в режим свободного перемещения; пользователь может свободноперетаскивать их по странице и установить в новом положении, которое будетсохранено на будущее.

Для каждого элемента, переводимого в режим свободного перемещения, необ-ходимо добавить блок DragOverlayProperties и задать его свойству TargetControllDидентификатор элемента. Также необходимо убедиться в том, что его свойствоEnabled равно true.

<span style="background-color:yellow;" runat="server" id="Msg">Enter some text:</span>

<br /><asp:TextBox ID="TextBoxl" runat="server" /><asp:Button ID="Buttonl" runat="server" text="Click" /><atlas:DragOverlayExtender ID="DragOverlayl" runat="server">

<atlas:DragOverlayProperties Enabled="true" TargetControlID="Msg" />/></atlas:DragOverlayExtender>

Page 146: Microsoft ASP.NET 2.0 AJAX

1 4 6 Глава 4. Элементы Microsoft ASP.NET AJAX

В этом фрагменте мы видим тег <span>, преобразованный в перетаскиваемыйэлемент страницы. Все элементы первоначально отображаются в своей исходнойпозиции; простым перетаскиванием их можно переместить в другую позицию настранице. Обратите внимание: ни один элемент нельзя вывести за физическиепределы страницы. Другими словами, перетаскивание за пределы последнегофрагмента содержимого запрещено. Если вы попытаетесь это сделать, перетас-киваемый компонент быстро возвращается на исходное место (впрочем, выгля-дит довольно эффектно).

ПРИМЕЧАНИЕРасширитель DragOverlay, как и DragPanel, генерирует код для вызова аспекта поведе-ния Floating клиентской стороны (этот и другие клиентские аспекты поведения рас-сматриваются в главе 5). Чем же DragPanel отличается от DragOverlay?В отличие от DragPanel расширитель DragOverlay не ограничивается перетаскивани-ем элементов ASP.NET Panel и тегов <div>. Тем не менее при перетаскивании элемен-тов, обрабатывающих перемещения мыши (кнопки, текстовые поля и т. д.), могутвозникнуть проблемы. Следовательно, в большинстве случаев он все же будет приме-няться для перетаскивания панелей. Элемент DragPanel позволяет явно задать мани-пулятор для перетаскивания; у расширителя DragOverlay в роли манипулятора исполь-зуется тело перетаскиваемого элемента.

Необязательное свойство ProfileProperty позволяет сохранить текущую пози-цию свободно перемещаемого элемента в пользовательском профиле заданногосвойства. Тем самым обеспечивается сохранение изменений, вносимых пользо-вателем, и их автоматическое восстановение при обновлении страниц. Однакодля этого на форме необходимо разместить компонент ProfileScriptService (он бу-дет рассмотрен наряду с другими клиентскими элементами Atlas в главе 6). Покадостаточно сказать, что он представляет собой внутреннюю веб-службу, котораяпредоставляет клиентскому сценарию серверный объект HttpContext.Profile.

ПРИМЕЧАНИЕВсеми параметрами свойств целевых элементов расширителей Atlas можно управлятьна программном уровне. Разработчик использует коллекцию TargetProperties, предо-ставляемую каждым расширителем, и получает нужное свойство по индексу (нумера-ция индексов начинается с 0).protected void Page_Load(object sender, EventArgs e){

DragOverlayl.TargetProperties[0].Enabled = true;}

Этот фрагмент разрешает свободное перемещение целевого элемента первого свойстваDragOverlay.

Расширитель CascadingDropDownРасширитель CascadingDropDown присоединяется к элементу DropDownList и обес-печивает его автоматическое заполнение на основании текущего состояния вы-деления одного или нескольких родительских элементов DropDownList.

Page 147: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 147

Расширитель CascadingDropDown проектировался для весьма распространен-ной ситуации, в которой содержимое одного раскрывающегося списка зависитот того, какая строка выделена в другом списке. При такой схеме вам не нужнопересылать клиенту весь набор данных, чтобы дочерний список выбирал под-множество строк, отображаемых в соответствии с текущим выделением родите-ля. Предположим, вы хотите, чтобы пользователь выбрал страну и город в этойстране. Расширитель CascadingDropDown упрощает решение этой задачи: для это-го он внедряет в клиентскую страницу связующий код, а также делает некоторыепредположения относительно структуры кода страницы.

Предполагается, что вся логика, определяющая содержимое элементов Drop-DownList, находится в веб-службе. В свою очередь, веб-служба может использо-вать любой подходящий механизм сохранения и поиска данных. Впрочем, онав некоторой степени ограничивается схемой, определяемой контрактом. В част-ности, веб-служба должна содержать метод со следующей сигнатурой:

[System.Web.Services.WebMethocTpublic CascadingDropDownNameValue[] GetDropDownContents(

string knownCategoryValues, string category){

}

Конечно, имя метода может быть другим. Внутренний тип коллекции Casca-dingDropDownNameValue предназначен для хранения пар «имя/значение», отобра-жаемых в раскрывающемся списке. Каждому раскрывающемуся списку, связан-ному с расширителем, назначается некоторая категория:

<act:CascadingDropDown ID="CascadingDropDownl" runat="server"><act:CascadingDropDownProperties TargetControlID="DropDownListl"

Category="Country"PromptText="Please select a country"ServiceMethod="GetDropDownContentsPageMethod" />

<act:CascadingDropDownProperties TargetControlID="DropDownList2"Category="City"PromptText="Please select a city"_oadingText="Please, wait ..."ServicePath="CityFinderService.asmx"ServiceMethod="GetDropDownContents"ParentControlID="DropDownListl" />

</act:CascadingDropDown>

Содержимое свойства Category представляет собой любое имя, по которо-му метод веб-службы может узнать, какие данные он должен получить, а такжеопределить смысл входных аргументов. Свойство PromptText определяет текст,который должен выводиться в раскрывающемся списке при отсутствии выде-ления (как правило, элемент при этом заблокирован). Свойство LoadingText оп-ределяет текст, отображаемый в процессе заполнения раскрывающегося списка.Свойство ServiceMethod указывает, какой метод должен вызываться для запол-нения списка. Если свойство ServicePath не задано, предполагается, что дол-жен использоваться метод страницы. Наконец, свойство ParentControllD создает

Page 148: Microsoft ASP.NET 2.0 AJAX

1 4 8 Глава 4. Элементы Microsoft ASP.NET AJAX

иерархию и указывает, что список является дочерним по отношению к другому(родительскому) списку.

Каждый раз, когда в родительском элементе DropDownList изменяется выделе-ние, расширитель обращается с вызовом к веб-службе и получает список значе-ний для следующего элемента DropDownList в иерархии. Если выделение отсутст-вует, расширитель автоматически блокирует элемент (рис. 4.14).

Рис. 4.14. Расширитель CascadingDropDown с двумя раскрывающимися списками

Расширитель ResizableControlБольшинству пользователей нравятся страницы, в которых они могут динамическиизменять размеры некоторых элементов HTML — например, панелей с текстомили графикой. Расширитель ResizableControl связывается с элементом веб-страни-цы и предоставляет графический интерфейс для изменения размеров этого элемен-та. При помощи манипулятора, расположенного в правом нижнем углу элемента,пользователь изменяет размеры элемента так, как если бы он был обычным ок-ном. Возьмем следующий пример разметки:

<asp:Panel ID="Panel1" runat="server" Style="overflow:hidden"Width="130px" Height="65px">

<asp:Image ID="Imagel" runat="server" ImageUrl="-7images/atlas.gif"Style="width:100^; height:100X;" />

</asp:Panel>

<asp:Panel ID="Panel2" runat="server" Style="overflow:auto"Width="130px" height="100px">

This text resizes itself to be as large as possiblewithin its container.

</asp:Panel>

Как видите, первая панель содержит графическое изображение, а вторая — простой текст. Для правильной работы расширителя необходима установка не-которых атрибутов CSS. В частности, для графики атрибут overflow обычно зада-ется равным hidden, а для текста — auto. Атрибут overflow управляет отображени-ем полос прокрутки в том случае, если содержимое элемента выходит за пределызарезервированного пространства. В приведенном примере изображение растя-гивается или сокращается, а текст прокручивается.

Очень важно назначить панелям правильный исходный размер. В частности,для изображений размер окружающей панели должен совпадать с размером изо-бражения. Размер панелей, окружающих текст, также должен задаваться явно.

<act:ResizableControlExtender ID="Resizablel" runat="server"><act:ResizableControlProperties

Page 149: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 4 9

TargetControlID="Panel1"ResizableCssClass="resizingStyle"HandleCssClass="handleStyle" />

<act:ResizableControlPropertiesTargetControlID="Panel2"ResizableCssClass="resizingStyle"HandleCssClass="handleStyle" />

</act:ResizableControlExtender>

Расширитель ResizableControl обладает двумя обязательными свойствами:TargetControllD и HandleCssClass. Первое свойство определяет элемент, размерыкоторого требуется изменить, а второе — имя класса CSS, применяемого к мани-пулятору. Также имеется дополнительное свойство ResizableCssClass, котороеопределяет класс CSS, применяемый к элементу в процессе изменения размеров.Например, с его помощью можно изменить цвет границы для визуального вы-деления операции. Типичный класс CSS манипулятора выглядит примерно так:

.handleStyle{

width:16рх;height:16px;background-image:url(-/images/HandleGrip.gif);overflow:hidden;cursor:se-resize;

}

На рис. 4.15 показан расширитель в действии.

Рис. 4.15. Расширитель ResizableControl в действии

Page 150: Microsoft ASP.NET 2.0 AJAX

1 5 0 Глава 4. Элементы Microsoft ASP.NET AJAX

Расширитель ResizableControl также поддерживает два клиентских события(onresizing и onresize), которые могут активизировать код JavaScript для выпол-нения более сложных операций (например, увеличения размера шрифта длязаполнения области текстом). Расширитель позволяет определить минимальныйи максимальный размеры при изменении размера элемента. Все изменения, свя-занные с изменением размеров элемента, автоматически сохраняются между об-новлениями страницы.

Расширитель DynamicPopulateРасширитель DynamicPopulate заменяет разметку заданного элемента разметкой, по-лученной при вызове метода веб-службы. Его можно рассматривать как упрощен-ную версию элемента UpdatePanel, описанного в главе 3. DynamicPopulate отслежи-вает клиентское событие и генерирует удаленный вызов. Возвращаемая строкавставляется в модель DOM страницы в качестве потомка целевого элемента. Пример:

<input type="button" id="Buttonl" runat="server" value="Refresh ..." /><hr /><t»Last updated:&nbsp;</t»<asp:Panel runat="server" ID="Msg" Style="padding:2px;height:2em;"> </asp:Panel>

<act:DynamicPopulateExtender ID="mpe" runat="server"><act:DynamicPopulateProperties

TargetControlID="Msg"ClearContentsDuringUpdate="true"PopulateTriggerControlID="Buttonl"ServiceMethod="GetTimeOnServer"UpdatingCssClass="updating" />

</act:DynamicPopulateExtender>

Когда пользователь щелкает на заданном объекте (в данном случае на кноп-ке с именем Button"!), расширитель берется за дело. Он вызывает метод Get-TimeOnServer и заменяет поддерево, корнем которого является элемент Msg, ре-зультатом вызова. Метод GetTimeOnServer является методом веб-службы. URLслужбы задается свойством ServicePath. Если это свойство не задано, предпола-гается, что метод является методом страницы, определяемым либо в кодовомфайле страницы, либо встроенным в теге <script>:

[System.Web.Services.WebMethod;public string GetTimeOnServer(string contextKey){

// Использовать параметр contextKey для приема данных от клиента.

// Получение вывода - вероятно, разметки HTMLreturn DateTime.UtcNow.ToStringO;

}

Логическое свойство ClearContentsDuringUpdate управляет стиранием содержи-мого целевого элемента во время обновления. Чтобы во время операции ото-бражался специальный стиль или графическое изображение, задайте стиль CSSв свойстве UpdatingCssClass. Атрибут CSS background-image задает выводимоефоновое изображение.

На рис. 4.16 показан результат работы приведенного кода.

Page 151: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 5 1

Рис. 4.16. Расширитель DynamicPopulate в действии

Для активизации динамического заполнения целевого элемента может исполь-зоваться любой элемент HTML. Он вовсе не обязан быть кнопкой отправки дан-ных (например, LinkButton или Button). В этом случае страница будет выполнятьобычный возврат данных, и вы лишитесь преимуществ платформы Atlas.

ПРИМЕЧАНИЕДля динамического заполнения элемента DOM также может использоваться фрагменткода JavaScript. В этом случае свойству CustomScript задается имя глобальной функцииJavaScript. При использовании как сценария, так и серверного метода можно восполь-зоваться свойством ContextKey расширителя для передачи коду произвольной строки.

Расширитель PagingBulletedListПредставьте страницу, на которой должен выводиться длинный список — скажем,перечень клиентов. Стандартное решение основано на использовании многостра-ничной сетки. Сетки ASP.NET выполняют возврат данных для каждой новойстраницы, но упаковка сетки в элементы UpdatePanel позволяет изящно решитьпроблему. Но если вам всего лишь требуется перечислить набор записей в видемаркированного списка, сетка оказывается излишне тяжеловесным элементом.

Page 152: Microsoft ASP.NET 2.0 AJAX

1 5 2 Глава 4. Элементы Microsoft ASP.NET AJAX

Элемент ASP.NET BuiletedList выводит содержимое источника данных с ис-пользованием разнообразных интерфейсов, основанных на маркировке пунктовсписка. Тем не менее постраничного вывода данных он не поддерживает. Рас-ширитель PagingBulletedList оказывается на удивление простым и эффективнымсредством постраничного перебора содержимого элемента BulletedList.

Рассмотрим следующий код:<asp:BulletedList ID="BulletedListl" runat="server" DisplayMode="Text"

DataSourceID="ObjectDataSourcel" DataTextField="CompanyName" />

<asp:ObjectDataSource ID="ObjectDataSourcel" runat="server"TypeName="IntroAtlas.CustomerManager"SelectMethod="LoadAll">

</asp:ObjectDataSource>

Страница генерирует более 80 маркированных пунктов — по одному длякаждого клиента в базе данных Northwind. Применяя расширитель к элементуBulletedList, вы получаете результат, показанный на рис. 4.17.

Рис. 4.17. Расширитель PagingBulletedList в действии

Код расширителя выглядит так:<act:PagingBul I etedListExtender ID="PagingBulIetedListl" runat="server">

<act:PagingBulIetedListPropertiesTargetControlID="BulIetedListl"ClientSort="true"IndexSize="2"Separator^' - " SelectIndexCssClass="selectedPage" />

</act:PagingBulIetedListExtender>

Page 153: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 5 3

Расширитель делит все связанные элементы на страничные блоки и создаетссылку на каждый блок. Страница может содержать фиксированное количествозаписей или все записи с заданным префиксом. Свойство IndexSize указывает,сколько букв в отображаемом тексте должно использоваться для создания стра-ницы. Если задать его равным 1, будет построено простое алфавитное меню. Приувеличении значения до 2 представление данных становится более детальным — каждая страница содержит записи с именами, начинающимися с двухбуквенногопрефикса. Вместо IndexSize можно воспользоваться свойством MaxltemsPerPage.В этом случае каждый страничный блок (кроме последнего) будет содержать за-данное количество записей.

Свойство Separator определяет символ, используемый для разделения элемен-тов меню. Свойства Class и UnselectlndexCssClass задают классы CSS соответст-венно для выделенных и невыделенных элементов меню. Наконец, если свойст-во ClientSort равно true, данные перед выводом автоматически сортируются настороне клиента.

Расширители полей вводаВеб-страницы все еще зависят от встроенных возможностей языка разметкиHTML, обеспечивающих возможность ввода пользователями данных на формахи в полях ввода. Однако элементы ввода HTML порой оказываются слишкомограниченными и простыми для современных приложений и пользователей.По этой причине старый добрый элемент <input type=«text»> и его аналог ASP.NETTextBox нуждаются в дополнительных возможностях. Atlas предоставляет парурасширителей, преобразующих классическое поле ввода в более интерактивное,дружественное к пользователю текстовое поле.

Расширитель AutoCompleteВвод данных в текстовых полях иногда бывает утомительным делом, особеннокогда вам приходится снова и снова повторять один и тот же текст. По этойпричине в браузерах уже довольно давно появилась функция автозаполнения.Традиционно в контексте браузера под этим термином понимается отслежи-вание всех URL, вводившихся пользователем. Когда пользователь начинаетвводить длинный и плохо запоминаемый URL, браузер поможет ему своевре-менной подсказкой.

В некоторых браузерах (таких, как Internet Explorer 5 и более новых вер-сий) автозаполнение также используется для любых текстовых полей на формахHTML. Браузер сохраняет на локальном компьютере любые данные, веденныев поле ввода с некоторым именем, и предоставляет эту информацию на всехстраницах сайта, содержащих одноименный элемент HTML. Функция автозапол-нения интегрируется в браузер и является полностью прозрачной для пользова-телей и разработчиков. Список предлагаемых вариантов ввода строится посте-пенно и не может контролироваться авторами страниц.

Расширитель Atlas AutoComplete распространяет функцию автозаполненияна любой элемент ASP.NET TextBox; что еще важнее, он дает авторам страниц

Page 154: Microsoft ASP.NET 2.0 AJAX

1 5 4 Глава 4. Элементы Microsoft ASP.NET AJAX

возможность программного определения списка рекомендуемых вариантов за-полнения (получаемого в результате вызова веб-службы).

<asp:TextBox ID="CustomerName" runat="server" /><atlas:AutoCompleteExtender runat="server" ID="AutoCompleteExtenderl">

<atlas:AutoCompletePropertiesTargetControlID="CustomerName"Enabled="true"MinimumPrefixLength="l"ServicePath="Suggestions.asmx"ServiceMethod="GetSuggestions" />

</atlas:AutoCompleteExtender>

Текстовое поле из этого фрагмента автоматически заполняется данными, воз-вращаемыми методом GetSuggestions заданной веб-службы. Свойства расшири-теля ServicePath и ServiceMethod определяют службу, предоставляющую данныедля автозаполнения; свойство MinimumPrefixLength указывает, сколько символовдолжен ввести пользователь для активизации функции автозаполнения. В при-веденном примере автозаполнение включается с первого введенного символа.

ПРИМЕЧАНИЕВеб-служба должна быть локальной, то есть установленной на том же сервере и в од-ном приложении с используемой страницей. Учтите, что это условие действует длявсех веб-служб, используемых расширителями Atlas.

Метод веб-службы, используемый для получения вариантов заполнения, дол-жен обладать фиксированной сигнатурой:

[System.Web.Services.WebMethod[public string[] GetSuggestions(string prefixText, int count){

}

Аргумент prefixText обозначает текст, введенный пользователем до настояще-го момента; аргумент count задает желательное количество вариантов. Результатотображается на раскрывающейся панели под текстовым полем. Пользовательможет выбрать один из предложенных вариантов при помощи мыши или клавиа-туры. В следующем фрагменте показан метод веб-службы, который возвращаетподмножество имен клиентов, начинающихся с заданного префикса (рис. 4.18).

public class SuggestionService : System.Web.Services.WebService{

[System.Web.Services.WebMethod[public string[] GetSuggestions(string prefixText, int count){

int i=0;DataView data = GetDataO;data = FilterData(data, prefixText);string [] suggestions = new string[data.Count];foreach (DataRowView row in data)

suggestions[i++] = row["companyname"].ToStringO ;

Page 155: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 5 5

return suggestions;

private DataView GetData()

{

DataView view = (DataView)HttpContext.Current.Cache["Suggestions"];

if (view == null)

{

SqlDataAdapter adapter = new SqlDataAdapter(

"SELECT * FROM customers", " . . . " ) ;

DataTable table = new DataTable();

adapter.Fill(table);

view = table.DefaultView;

// Сохранение всего набора данных в кэше ASP.NET

// для повторного использования в будущем.

HttpContext.Current.Cache["Suggestions"] = view;

return view;

private DataView FilterData(DataView view, string prefix)

{

// Фильтрация нежелательных строк.

view.RowFilter = String.Format("companyname LIKE '{0}%'", prefix);

return view;

Рис. 4.18. Расширитель AutoComplete в действии

Расширитель AutoComplete не определяется в библиотеке ACT, а интегриро-ван в инфраструктуру Atlas.

Page 156: Microsoft ASP.NET 2.0 AJAX

1 5 6 Глава 4. Элементы Microsoft ASP.NET AJAX

Расширитель TextBoxWatermarkРасширитель TextBoxWatermark определяет текст, который отображается по умол-чанию при отсутствии данных в текстовом поле. Расширитель отображает и скры-вает текст по мере необходимости.

<act:TextBoxWatermarkExtender runat="server" ID="TextBoxWatermarkl"><act:TextBoxWatermarkProperties TargetControlID="TextBoxl"

WatermarkText="Type First Name Here"WatermarkCssClass="watermarked" />

<act:TextBoxWatermarkProperties TargetControlID="TextBox2"WatermarkText="Type Last Name Here"WatermarkCssClass="watermarked" />

</act:TextBoxWatermarkExtender>

Расширитель определяется в ACT и использует свойство TargetControllD дляопределения целевого текстового поля. Свойство WatermarkText определяет ото-бражаемый текст, а свойство WatermarkCssClass — стиль CSS, используемый дляоформления текста подсказки (рис. 4.19).

Рис. 4.19. Расширитель TextBoxWatermark в действии

Расширитель FilteredTextBoxРасширитель FilteredTextBox отфильтровывает некоторые символы из буфера за-данного текстового поля. Он отличается от элемента проверки данных тем, чтопросто запрещает пользователю вводить недопустимые символы, тогда как эле-мент проверки данных активизируется на более поздней стадии, когда пользова-тель выходит из поля ввода.

<strong>How old are you?</strong><asp:TextBox ID="TextBoxl" runat="server" /><act:FilteredTextBoxExtender ID="Filteredl" runat="server" >

<act:FiIteredTextBoxPropertiesTargetControlID="TextBoxl"rilterType="Numbers" />

</act:FiIteredTextBoxExtender>

Page 157: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 5 7

Текстовое поле в этом примере предназначено для ввода числа, обозначающе-го возраст пользователя. Естественно, в нем могут вводиться только цифры. Длявыполнения этого ограничения расширитель добавляет к текстовому полю фраг-мент кода JavaScript, отфильтровывающий нежелательные символы.

Расширитель поддерживает несколько свойств, в том числе свойство FilterType,которое определяет тип фильтра, применяемого к вводу. Свойство принимаетследующие значения: Numbers (числа), UppercaseLetters (прописные буквы),LowercaseLetters (строчные буквы) и Custom (пользовательский). Смысл первыхтрех значений очевиден. При указании типа фильтра Custom свойству ValidCharsзадается строка, разделенная запятыми, в которой каждое поле определяет раз-решенный символ. Например, следующий код разрешает пользователю вводитьтолько символы A и B в любом регистре:

<act:FilteredTextBoxExtender ID="Filteredl" runat="server" ><act:FiIteredTextBoxProperties

TargetControlID="TextBoxl"rilterType="Custom"ValidChars="A,a,B,b" />

</act:FiIteredTextBoxExtender>

Объединение нескольких фильтров для одного текстового поля не допускает-ся. Например, если вы хотите отфильтровывать все символы, кроме букв, вам неудастся добавить два расширителя FilteredTextBox для одного элемента. Вместоэтого придется воспользоваться пользовательсим фильтром, у которого в свой-стве ValidChars перечислены все допустимые символы.

ВНИМАНИЕФильтрация на стороне клиента, как и проверка данных, обеспечивается работой кодаJavaScript. Это означает, что запрет JavaScript в клиентском браузере приведет к от-ключению фильтрации или проверке данных. В любом случае не стоит безоговорочнодоверять данным, введенным пользователем в текстовом поле, — используйте фильт-рацию и проверку на стороне сервера, прежде чем использовать данные в критическихоперациях.

Расширитель NumericUpDownРасширитель NumericUpDown добавляет к элементу TextBox пару кнопок со стрел-ками, при помощи которых пользователь увеличивает и уменьшает отображае-мое значение. Интересно заметить, что возможность увеличения и уменьшенияприменима не только к числовым данным, но и к перечисляемым типам, опреде-ляемым пользователем.

<strong>How old are you?</strong><asp:TextBox ID="TextBoxl" runat="server" Width="lOOpx" />

<act:NumericlIpDownExtender ID="UpDownl" runat="server"><act:NumericUpDownProperties

Width="100"TargetControlID="TextBoxl" />

</act:NumericUpDownExtender>

Page 158: Microsoft ASP.NET 2.0 AJAX

1 5 8 Глава 4. Элементы Microsoft ASP.NET AJAX

Для управления размером поля ввода следует задать свойство Width как длятекстового поля, так и для расширителя. Обратите внимание: свойство Width рас-ширителя обозначает общую ширину элемента вместе со стрелками (рис. 4.20).

Рис. 4.20. Расширитель NumericUpDown в действии

По умолчанию приращение равно +1 или - 1 . Впрочем, свойству RefValues по-зволяет задать последовательность значений при переборе. Свойство представ-ляет собой строку с полями, разделенными символом «;» (точка с запятой):

<act:NumericUpDownPropertiesWidth="100"RefValues="Sun;Mon;Tue;Wed;Thu;Fri;Sat"TargetControlID="TextBoxl" />

Расширитель также может воспользоваться веб-службой для вычисленияследующего или предыдущего значения. В этом случае свойства ServiceUpPathи ServiceUpMethod определяют службу и метод для выполнения операции уве-личения (то есть определения следующего значения), а аналогичные свойстваServiceDownPath и ServiceDownMethod предназначены для операции уменьше-ния. Клиент также может передавать произвольные данные методам служб в свой-стве Tag.

ПРИМЕЧАНИЕИспользование расширителя NumericUpDown само по себе еще не гарантирует удоб-ства пользователя. Дело в том, что расширитель NumericUpDown не заставляет тексто-вое поле принимать только те значения, которые были сгенерированы в процессеперебора. Например, ничто не помешает ввести слово в числовом текстовом поле сосвязанным расширителем NumericUpDown. Чтобы этого не произошло, объединитерасширитель NumericUpDown с расширителем фильтрации символов и воспользуй-тесь свойством MaxLength элемента TextBox для ограничения максимального количе-ства символов.

Расширитель PasswordStrengthДаже самая защищенная система не сможет ничего сделать для защиты вашегосервера, если авторизованные пользователи будут использовать слабые, легко

Page 159: Microsoft ASP.NET 2.0 AJAX

Серверные расширители Atlas 1 5 9

подбираемые пароли. В последнее время появился целый ряд методов для созданиясильных паролей. Расширитель PasswordStrength присоединяется к элементуTextBox и измеряет силу (то есть устойчивость) текущего содержимого поля приего использовании в качестве пароля.

С точки зрения синтаксиса расширитель может присоединяться к любымэлементам TextBox; однако с точки зрения семантики его стоит присоединятьтолько к элементам TextBox, предназначенным для ввода пароля. РасширительPasswordStrength вряд ли принесет реальную пользу на странице входа в систе-му, где пользователь должен ввести пароль для получения доступа к некоторойфункциональности. Скорее, он пригодится на форуме, где пользователи вводятинформацию о себе для получения доступа к системе.

<h2>Choose your password</h2><asp:TextBox ID="TextBoxl" runat="server" /><act:PasswordStrength runat="server">

<act:PasswordStrengthExtenderProperties TargetControlID="TextBoxl" /></act:PasswordStrength>

Расширитель проверяет текущий текст по набору критериев, установленныхавтором страницы. Результат проверки выводится либо в текстовом виде, либов виде полосы-индикатора, обозначающей уровень сложности выбранного па-роля. Работа расширителя в конфигурации по умолчанию показана на рис. 4.21.

Рис. 4 .21 . Расширитель PasswordStrength в действии

Обратная связь выводится в виде простого текста и изменяется динамическипо мере заполнения буфера. Свойства расширителя условно делятся на две кате-гории: внешний вид и поведение.

К первой категории относится свойство DisplayPosition, задающее позицию тек-ста обратной связи (сверху, снизу, слева или справа), и свойство Strengthlndicator-Туре, выбирающее тип визуальной обратной связи. Допустимые значения свойст-ва StrengthlndicatorType — Text и Barlndicator. Если задано значение Text, свойствоPrefixText определяет текст, используемый при составлении сообщения обратнойсвязи. В свойстве TextCssClass указывается класс CSS, определяющий стиль со-общения обратной связи.

Если для обратной связи выбран тип Barlndicator, она отображается в виде ин-дикаторной полосы, заключенной в рамку. Стиль полосы определяется свойст-вами BarBorderCssClass и BarlndicatorCssClass.

Page 160: Microsoft ASP.NET 2.0 AJAX

1 6 0 Глава 4. Элементы Microsoft ASP.NET AJAX

Критерии проверки пароля определяются свойствами RequiresUpperAndLower-CaseCharacters, PreferredPasswordLength, MinimumNumericCharacters и Minimum-SymbolCharacters. По умолчанию длина пароля равна 10 символам и другие про-верки содержимого поля не применяются.

Расширитель вычисляет оценку пароля на основании заданных критериев. Ре-зультат отображается в виде полосы индикатора или текстового сообщения, какна рис. 4.21. Текстовые сообщения задаются в свойстве TextStrengthDescriptionsв виде перечня описаний, разделенных символом «;». Можно задать от 2 до 10 опи-саний, упорядоченных по возрастанию устойчивости пароля.

Обратная связь от расширителя делится на две части — оценку и сообщениесостояния. Оценка используется для обновления индикатора или отображенияописания. Сообщение состояния содержит справочную информацию и отобража-ется на вспомогательном элементе, определяемом свойством HelpStatusLabellD.

<asp:TextBox ID="TextBoxl" runat="server" /> <br /><asp:Label runat="server" ID="Label1" />

<act:PasswordStrength runat="server"><act:PasswordStrengthExtenderProperties TargetControlID="TextBoxl"

DisplayPosition="RightSide"PreferredPasswordLength="12"HelpStatusLabelID="Labell" />

</act:PasswordStrength>

Элемент Label 1 получает сообщение с предложениями относительно того, какобеспечить соответствие пароля поставленным требованиями. Сообщение можетоставаться скрытым и отображаться по щелчку на специальной кнопке. В этомслучае следует задать значения двух новых свойств: HelpHandlePosition и Help-HandleCssClass. Первое свойство задает позицию отображения кнопки, а второе — ее стиль.

<act:PasswordStrength runat="server"><act:PasswordStrengthExtenderProperties TargetControlID="TextBoxl"

DisplayPosition="BelowRight"PreferredPasswordLength="12"HelpHandlePosition="RightSide"HelpHandleCssClass="helpHandle" />

</act:PasswordStrength>

Оформление кнопки задается стилем CSS:.helpHandle{

width:16px;height:14px;background-image:url(images/Question.png);overflow:hidden;cursor:help;

}

На рис. 4.22 показано, как выглядит полученная страница.

Page 161: Microsoft ASP.NET 2.0 AJAX

Заключение 1 6 1

Рис. 4.22. Расширитель PasswordStrength с кнопкой вызова справки

ЗаключениеМногие разработчики ASP.NET стремятся к тому, чтобы их страницы обладалиболее широкими возможностями и стали более удобными для пользователей.С технологической точки зрения эту задачу невозможно решить без использова-ния JavaScript и кода клиентской стороны. Практически все возможности, нахо-дящиеся под контролем клиента, от нестандартных аспектов поведения HTMLдо асинхронных вызовов, требуют применения кода JavaScript или других анало-гичных средств — таких, как язык Atlas XML Script. Что делать, если вы недоста-точно хорошо владеете JavaScript и вам не хочется изучать новый диалект XML?

Серверно-центрическая модель программирования Atlas представляет в вашераспоряжение расширители элементов, которые позволяют наделять существую-щие элементы новыми функциями и возможностями. Расширитель определяетнестандартный аспект поведения целевого элемента. Поведение клиентскойфункциональности выражается с использованием кода JavaScript, но связывает-ся с серверными элементами с применением классической модели программиро-вания ASP.NET.

Абсолютное большинство расширителей элементов, упоминавшихся в этойглаве, реализуется в виде нестандартных серверных элементов, а их расширен-ное поведение определяется посредством фрагмента кода JavaScript, внедряемо-го в виде ресурса. Другие аспекты поведения также могут определяться как авто-номные элементы клиентской библиотеки Atlas, которая будет рассматриватьсяв следующей главе.

Page 162: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 5 Библиотека Microsoft AJAX

В этой главе:i Расширения JavaScriptI Основные компонентыI Элементы пользовательского интерфейса

Чтобы переход с классической платформы Microsoft ASP.NET на платформуASP.NET Atlas проходил как можно проще и естественнее, в предыдущих главахя описывал возможности платформы Atlas в основном с точки зрения серверно-го программирования. Однако следует помнить, что мощь Atlas в значительноймере сосредоточена на стороне клиента и тесно связана с клиентской функцио-нальностью браузеров и платформ. Серверо-центрическая модель разработки,проанализированная в главах 3 и 4, представляет собой всего лишь набор «обер-ток», генерирующих на сервере весь необходимый код клиентской стороны, ко-торый разработчику иначе пришлось бы писать вручную.

Чтобы в полной мере понять мощь платформы Atlas и научиться создаватьинтерактивные приложения, необходимо поближе познакомиться с инфраструк-турой и широким диапазоном компонентов, упрощающих клиентское програм-мирование в Atlas.

Для обеспечения совместимости браузеров клиентская инфраструктура Atlasнаписана на JavaScript, но в объектно-ориентированном ключе. Язык JavaScriptподдерживает работу с объектами и позволяет создавать пользовательские объ-екты. Тем не менее его никак нельзя назвать современным, объектно-ориенти-рованным механизмом построения библиотек классов в духе .NET Framework.Atlas поднимает язык JavaScript на новый уровень, с расширением системы ти-пов и введением концепций пространств имен и наследования. Кроме того, AtlasJavaScript поддерживает интерфейсы, перечисляемые типы и ряд вспомогатель-ных функций для работы со строками и массивами. Эти расширения программи-руются на основе базового набора команд языка объекта JavaScript и хранятсяв файлах .js, образующих runtime-среду Atlas.

В этой главе мы сначала разберемся, как использовать Atlas-расширенияJavaScript (такие, как пространства имен, интерфейсы и наследование), а затемподробнее займемся пространствами имен и классами, из которых складываетсяклиентская среда Atlas.

Page 163: Microsoft ASP.NET 2.0 AJAX

Расширения JavaScript 163

Расширения JavaScriptВероятно, написание широкофункциональных и сложных сред — таких, какAtlas — на обычном JavaScript выходит за рамки человеческих возможностей.Однако использование любого другого языка создает серьезные проблемы со-вместимости браузеров и подрывает главную причину успеха парадигмы AJAX.

Runtime-среда AtlasХотя практически любой современный браузер поддерживает JavaScript и мо-дель DOM (Document Object Model) стандарта HTML 4.0, между разными вер-сиями DOM существует ряд тонких различий. Расширения Atlas JavaScriptдолжны абстрагировать различия между версиями DOM и предоставить средупрограммирования более высокого уровня — более простую в использовании,с лучше читающимся кодом и снижающую вероятность ошибок.

Основной механизм AtlasКак упоминалось в главе 2, для работы приложений Atlas необходим ряд сценар-ных файлов .js. Эти файлы содержат реализацию библиотеки Microsoft AJAXи предоставляют в распоряжение разработчика новые объектно-ориентирован-ные конструкции. Элемент ScriptManager отвечает за выбор стандартных сценар-ных файлов, внедряемых в страницу. Как минимум внедряется файл Atlas.js.Включение файла Atlas.js в клиентскую страницу упрощает программированиена JavaScript и автоматически обогащает клиентскую среду новым, расширен-ным набором объектов и объектно-ориентированных возможностей.

Ссылки на файлы Atlas JavaScript включаются в сборку Microsoft.Web.Atlasв виде ресурсов, но устанавливаются как файлы с исходным кодом (как в отла-дочной, так и в окончательной версии) для отладки и изучения.

ПРИМЕЧАНИЕИсходный код всех файлов Atlas JavaScript находится в папке ScriptLibrary основ-ного пути установки Atlas. По умолчанию используется путь Program Files\MicrosoftASP.NET\Atlas.

Инфраструктура расширений JavaScriptВ целом JavaScript является скорее объектно-базированным, нежели в полноймере объектно-ориентированным языком (в нем отсутствуют некоторые ключе-вые возможности, самая заметная из которых — наследование, хотя и существуетмеханизм псевдонаследования на базе prototype). Язык включает набор встроенныхвспомогательных объектов, в том числе Function, Object, Boolean, Array, Numberи String. Все встроенные объекты обладают свойством с именем prototype, дос-тупным только для чтения. Свойство prototype представляет базовую функцио-нальность, общую для всех новых элементов объекта данного класса. Новаяфункциональность добавляется в прототип класса в приложениях для расшире-ния и улучшения возможностей данного класса. Именно это происходит в Atlas.

Page 164: Microsoft ASP.NET 2.0 AJAX

1 6 4 Глава 5. Библиотека Microsoft AJAX

В файле Atlas.js все встроенные объекты JavaScript наделяются новыми воз-можностями. Например, Atlas расширяет объект JavaScript Function наборомметодов для реализации делегирования, абстрактных методов и наследования.Следующий краткий фрагмент Atlas.js демонстрирует сказанное:

// Определение абстрактного методаFunction.abstractMethod = function(){

throw 'Abstract method should be implemented';}// Определение функции обратного вызоваFunction.createCallback = function(method, context){

return function() { return method(context);

}}// Определение делегата (указателя на функцию)Function.createDelegate = function(instance, method){

return function() { return method.apply(instance, arguments);

}}// Расширение прототипа для поддержки базовых методовFunction.prototype.getBaseMethod = function(instance, methodName,baseTypeName){

}// Расширение прототипа для получения информации о базовом типеFunction.prototype.getBaseType = function() {

return this._baseType;}

В файле Atlas.js также определяется ряд переменных для хранения специфи-ческой информации типов (например, базовый тип и имя типа) — все эти кон-цепции не поддерживаются напрямую в браузерных реализациях JavaScript. Всеметоды, добавленные в прототип, «наследуются» всеми функциями, определяе-мыми в контексте любого приложения Atlas.

Кроме того, файл Atlas.js содержит код, определяющий новые объекты и рас-ширяющий существующие объекты JavaScript дополнительной функциональ-ностью. В табл. 5.1 перечислены основные глобальные объекты, определяемыев файле Atlas.js.

Таблица 5 . 1 . Глобальные объекты runtime-среды Atlas

Тип ОписаниеArray Расширение встроенного объекта Array. Содержит методы добавления,

вставки, удаления и очистки элементов массива. Также содержит методыдля проверки присутствия заданного элемента в массиве

Page 165: Microsoft ASP.NET 2.0 AJAX

Расширения JavaScript 165

Тип Описание

Boolean Расширение встроенного объекта Boolean. Определяет метод parse дляполучения логического значения по строке или любому выражениюс логическим результатом

Error Определяет метод createError, инкапсулирующий объект JavaScriptError, и добавляет более удобный конструктор для его создания

Function Расширение встроенного объекта Function. Содержит методы дляопределения классов, пространств имен, делегатов и других объектно-ориентированных средств

Number Расширение встроенного объекта Number. Определяет метод parse дляполучения числового значения по строке или любому выражениюс числовым результатом

Object Расширение встроенного объекта Object. Содержит методы для полученияинформации о типах (например, типа используемого объекта)

RegExp Расширение встроенного объекта RegExp. Определяет метод parse дляпостроения регулярного выражения по заданному значению

String Расширение встроенного объекта String. Содержит методы для работысо строками — такие, как trim, endsWith и startsWith. Также определяетглобальный метод format, родственный методу String.Formatуправляемого типа String

Type Содержит методы для создания перечисляемых типов и объявленияпространств имен

Простое включение серверного компонента ScriptManager в страницу ASP.NETдает возможность использовать дополнительные методы «родных» объектов, оп-ределяемые в runtime-среде Atlas. Например, следующий код будет работать аб-солютно нормально:

var s = "Dino";alert(s.startsWith('D'));

Встроенный объект JavaScript String не поддерживает метод startWith. Тем неменее следующий код Atlas.js успешно решает проблему:

String.prototype.endsWith = function(suffix) {return (this.substr(this.length - suffix.length) == suffix);

}String.prototype.startsWith = function(prefix) {

return (this.substr(0, prefix.length) == prefix);}

Объекты JavaScript не являются полноценными объектами с сильной типиза-цией. В частности, не существует абсолютно надежного механизма для определе-ния типа объекта, с которым вы работаете. Метод toString и оператор typeof лишьчастично решают проблему. Метод toString предназначен для получения строко-вого представления объекта, поэтому он всего лишь возвращает содержимое

Page 166: Microsoft ASP.NET 2.0 AJAX

1 6 6 Глава 5. Библиотека Microsoft AJAX

объекта для строк и чисел. Оператор typeof для имени пользовательского объек-та, с которым вы работаете, всегда возвращает строку object.

var р = new PersonC'Dino", "Esposito");alert(typeof(p));

Новый метод, добавленный в объект Object, обеспечивает точную идентифи-кацию типов. Используйте метод Object.getTypeName:

var р = new PersonC'Dino", "Esposito");alert(Object.getTypeName(p));

На этот раз в окне сообщения выводится строка Person вместо более общейстроки object. Чтобы увидеть, как это делается, достаточно заглянуть в исходныйкод метода getTypeName:

Object.getTypeName = function(instance){

return Object.getType(instance).getNameO ;}

Object.getType = function(instance){

var ctor = instance.constructor;if (!ctor || (typeof(ctor) != "function") || !ctor._typeName) {

return Object;}return instance.constructor;

}

В конечном итоге для получения имени типа используется метод getNameобъекта Function:

runction.prototype.getName = functionO {return this.jtypeName;

}

Как видите, метод getName просто возвращает значение внутренней перемен-ной. Оказывается, каждый новый объект сохраняет в переменной _typeNameстроку, представляющую имя класса. Например, в Atlas.js для класса Object в ка-честве имени типа явно сохраняется строка «Object»:

Object. jtypeName = 'Object';

Все встроенные объекты JavaScript модифицируются в файле Atlas.js с вклю-чением дополнительного свойства имени типа.

Итак, Atlas формирует поверх базовых, встроенных объектов JavaScript тол-стую абстрактную прослойку, преобразующую сценарный язык в некое подобиеобъектно-ориентированной сценарной прикладной среды. Если на секунду за-быть о хорошо знакомых концепциях и элементах синтаксиса JavaScript, можнопредставить, что перед вами совершенно новый язык. Runtime-среду Atlas мож-но сравнить со специализированной версией .NET Framework, а язык Atlas Java-Script — с упрощенной версией Microsoft Visual C#.

Page 167: Microsoft ASP.NET 2.0 AJAX

Расширения JavaScript 167

Глобальные функцииПрежде чем переходить к рассмотрению более интересных объектно-ориентиро-ванных расширений вроде пространств имен и наследования, давайте потратимнемного времени на пару удобных сокращений, которые можно использоватьв сценарном коде Atlas для ускорения разработки.

Одна из самых распространенных ошибок, встречающихся при написаниисценарного кода в веб-страницах, — прямой доступ к элементам HTML вместовызова метода getElementByld модели DOM. Предположим, на клиентской стра-нице имеется текстовое поле с именем TextBoxl. Следующая команда работает нево всех браузерах:

alert(TextBoxl.value);

Правильная форма, ратифицированная в проекте стандарта HTML DOM ко-митета W3C (World Wide Web), должна выглядеть так:

alert(document.getElementBylcK"TextBoxl").value);

Конечно, правильная форма занимает больше места и ее неудобно писать сно-ва и снова. На помощь приходит Atlas JavaScript со своей глобальной функцией$(). Фактически функция $() является сокращенной формой записи для функ-ции document.getElementByld. На странице Atlas следующее выражение функцио-нально эквивалентно приведенному ранее:

alert($("TextBoxl").value);

Аналогичная сокращенная запись существует и для поиска компонентов Atlasв runtime-иерархии Atlas. Для этой цели применяется функция $object() — сокра-щение для Application.findObject. Application — корневой объект в runtime-иерар-хии Atlas. Мы вернемся к этой теме позднее, при знакомстве с библиотекой Micro-soft AJAX.

Объектно-ориентированные расширенияв Atlas JavaScriptВ JavaScript объект Function является главным инструментом, используемым дляобъединения кода и свойств и построения новых компонентов. В Atlas JavaScriptобъект Function был расширен — в него была включена поддержка информациио типах, пространств имен, наследования, интерфейсов и перечисляемых типов.Посмотрим, как это было сделано.

Поддержка пространств именПространство имен (namespace) является средством группировки и класси-фикации типов, принадлежащих библиотеке. Пространство имен сам по себене является типом, но добавляет новую информацию в определение каждоготипа, содержащегося в нем, с целью его уточнения. На концептуальном уровнесвязь между пространством имен и содержащимся в нем типами можно срав-нить со связью между каталогом и содержащимся в нем файлами. В конечном

Page 168: Microsoft ASP.NET 2.0 AJAX

1 6 8 Глава 5. Библиотека Microsoft AJAX

счете единицей данных, с которой вы работаете, является файл; файлы иденти-фицируются по именам. Тем не менее для любой среды программированияодноименные файлы, находящиеся в разных каталогах, никак не связаны другс другом.

По умолчанию все пользовательские функции JavaScript принадлежат гло-бальному пространству имен. В Atlas JavaScript пользовательскую функциюможно поместить в конкретное пространство имен по сугубо организационнымсоображениям. Следующий фрагмент показывает, как объявить пользовательскийтип в Atlas JavaScript:

Type.registerNamespaceO IntroAtlas");IntroAtlas.Person = function(firstName, lastName){

var _firstName = firstName;var _lastName = lastName;this.getFirstName = functionO {

return _firstName;}this.getLastName = functionO {

return _lastName;}this.getName = functionO {

return _firstName + ' ' + JastName;}

}IntroAtlas.Person.registerClass('IntroAtlas.Person', null, null);

Метод Type.registerNamespace включает указанное пространство имен в runtime-среду. В какой-то степени этот метод эквивалентен конструкции namespacej...}в C# или Namespace .. End Namespace в Microsoft Visual Basic .NET.

ПРИМЕЧАНИЕТак как Atlas JavaScript представляет возможности runtime-среды, а не синтаксис язы-ка программирования, соответствие между Type.registerNamespace и аналогичнымиконструкциями C# или Visual Basic .NET является чисто условным. Во внутреннейреализации Type.registerNamespace ограничивается включением в текущую модельDOM информации для отслеживания текущего пространства имен.

Функция IntroAtlas.Person, определяемая за объявлением пространства имен,описывает тип Person в пространстве имен IntroAtlas. Наконец, только что опре-деленная функция должна быть зарегистрирована как класс в среде Atlas. Задачарешается вызовом метода registerClass для заданной функции. Метод registerClassопределяется в прототипе объекта Function, поэтому он наследуется всеми функ-циями. Во внутренней реализации метод registerClass задает свойству typeNameфункции первый параметр метода — фактическое имя класса.

Метод registerClass получает три параметра: открытое имя, которое будет ис-пользоваться для представления функции JavaScript как класса, родительскийкласс (если есть) и все интерфейсы, реализуемые классом.

Page 169: Microsoft ASP.NET 2.0 AJAX

Расширения JavaScript 169

Поддержка наследованияДавайте определим новый класс Citizen, который расширяет класс Person, допол-няя его парой свойств: адресом и номером социального страхования. В концефрагмента для только что определенной функции вызывается метод registerClass.

IntroAtlas.Citizen = function(firstName, lastName, ssn, address){

var _ssn = ssn;var _address = address;

this.getSSN = functionO {return _ssn;

}

this.getAddress = functionO {return _address;

}}IntroAtlas.Citizen.registerClass('IntroAtlas.Citizen', IntroAtlas.Person);

Обратите внимание: первый аргумент registerClass относится к строковомутипу, но во втором аргументе должна передаваться ссылка на объект.

Честно говоря, от этого кода особой пользы не будет. Вам как минимум необ-ходимо вызвать конструктор базового класса для инициализации полей, опреде-ленных в базовом классе. Метод initializeBase (определяемый в Function) получаети вызывает конструктор базового класса:

IntroAtlas.Citizen = function(firstName, lastName, ssn, address){IntroAtlas.Citizen.initializeBase(this, [firstName, lastName]);

}

При вызове initializeBase передается ссылка на текущий объект и массив пара-метров вызываемого конструктора. Запись [...] используется для определениямассива «на месте». Разработчики нередко создают производные классы, потомучто им потребовалось добавить новый метод или изменить поведение сущест-вующих методов. В объектно-ориентированных языках определяется специаль-ное ключевое слово для пометки переопределяемых методов. Как это сделатьв JavaScript? Давайте изменим класс Person и включим в него переопределяе-мый метод GetName:

Туре.registerNamespaceCIntroAtlas");

IntroAtlas.Person = function(firstName, lastName){

var _firstName = firstName;var _lastName = lastName;

this.getFirstName = function() { return _firstName;

}

Page 170: Microsoft ASP.NET 2.0 AJAX

1 7 0 Глава 5. Библиотека Microsoft AJAX

this.getLastName = function О { return _lastName;

}

this.getNamelnternal = functionO {return _firstName + ' ' + JastName;

}}IntroAtlas.Person.registerClass('IntroAtlas.Person', null);

IntroAtlas.Person.prototype.getName = functionO {return this.getNamelnternal();

}

Метод getName выведен из основного определения класса и присоединен к про-тотипу функции. Метод, включенный в прототип, используется совместно про-изводными классами, может переопределяться и вызываться из производныхклассов. Например, переопределение метода getName в производном классе Citizenпроисходит так:

IntroAtlas.Citizen = function(firstName, lastName, ssn, address){

IntroAtlas.Citizen.initializeBase(this, [firstName, lastName]);

var _ssn = ssn;var _address = address;

this.getSSN = functionO {return _ssn;

}this.getAddress = functionO {

return _address;}

}IntroAtlas.Citizen.registerClass('IntroAtlas.Citizen', IntroAtlas.Person);

IntroAtlas.Citizen.prototype.getName = functionO {return IntroAtlas.Citizen.callBaseMethod(this, "getName") +

" [" + this.getSSN() + " ] " ;}

Метод getName включается в прототип класса для дальнейшего переопреде-ления. Вызов callBaseMethod активизирует метод родительского класса.

ПРИМЕЧАНИЕПриватные члены класса недоступны в методах, включаемых в прототип функции.Любое свойство, к которому вы собираетесь обращаться из прототипизированного ме-тода, должно быть инкапсулировано в открытом методе (например, getNameInternal).

Поддержка интерфейсовИнтерфейс описывает совокупность логически связанных аспектов поведения,характерных для разных классов. В общем случае интерфейс может содержатьметоды, свойства и события; в JavaScript интерфейсы содержат только методы.

Page 171: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 7 1

Чтобы определить интерфейс, вы создаете функцию, состоящую из абстракт-ных методов. Абстрактный метод представляется методом abstractMethod, опре-деляемым для класса Function в Atlas.js. Метод abstractMethod — не ключевое сло-во, а реально существующий метод, при попытке вызова которого происходитисключение — определенно изящное решение.

Туре.registerNamespaceC IntroAtlas");IntroAtlas.IAddress = functionO {

this.getFullAddress = Function.abstractMethod;this.getStreet = Function.abstractMethod;this.getCity = Function.abstractMethod;this.getZipCode = Function.abstractMethod;

}IntroAtlas.IAddress.registerInterface('IntroAtlas.IAddress');

В Atlas JavaScript интерфейс представляет собой не что иное, как класс, поме-ченный как завершенный (sealed) и абстрактный, при его регистрации методомregisterlnterface. Чтобы реализовать интерфейс, класс JavaScript предоставляетвсе методы интерфейса, а сам интерфейс указывается при регистрации класса.Следующая команда регистрирует класс Citizen, производный от Person и реали-зующий интерфейс IAddress:

IntroAtlas.Citizen.registerClass('IntroAtlas.Citizen',IntroAtlas.Person, IntroAtlas.IAddress);

Однако учтите, что вы не получите никаких заблаговременных сообщений обошибке времени выполнения, если класс, объявивший о реализации некоторогоинтерфейса, не поддерживает все его методы. JavaScript является интерпрети-руемым, а не компилируемым языком, поэтому парсер JavaScript не будет знатьоб отсутствующих методах интерфейса вплоть до попытки их явного вызова.

ПРИМЕЧАНИЕЕсли класс реализует несколько интерфейсов, то все необходимые интерфейсы пере-числяются в дополнительных параметрах метода registerClass.

Основные компонентыБиблиотека Microsoft AJAX делится на три логических уровня: расширенияJavaScript, фундаментальные (или базовые) классы и классы пользовательскогоинтерфейса (рис. 5.1).

Как упоминалось в предыдущих разделах, расширения JavaScript наделяютвстроенные объекты JavaScript новыми методами и возможностями и добавля-ют методы регистрации для имитации объектно-ориентированных конструкций(таких, как классы, пространства имен, наследование и интерфейсы). В подсис-тему пользовательского интерфейса входят компоненты для определения кли-ентских аспектов поведения, операций перетаскивания, взаимодействия с мо-делью DOM, а также такие клиентские элементы, как текстовые поля, спискии источники данных.

Page 172: Microsoft ASP.NET 2.0 AJAX

1 7 2 Глава 5. Библиотека Microsoft AJAX

Классы пользовательского интерфейса

Пространствоимен Sys.UI

Пространствоимен Sys.Data

Пространство имен Sys.UI.Data

Фундаментальные классы

Пространствоимен Sys

Пространствоимен Sys.Net

Пространство имен Sys.Services

Расширения JavaScript

Function String Object

Рис. 5 . 1 . Структура библиотеки Microsoft AJAX

Фундаментальные классы образуют своего рода базовую библиотеку, в кото-рую вошли часто используемые классы для отладки, обработки событий, опе-раций со строками, работы с веб-службами, таймерами и счетчиками. Не стоити говорить, что все классы написаны на JavaScript и хранятся в файле Atlas.js.Как было показано ранее, Atlas JavaScript поддерживает пространства имен, по-этому классы библиотеки Microsoft AJAX принадлежат конкретным пространст-вам имен. Большинство классов фундаментального уровня библиотеки принад-лежит пространству имен Sys.

В этом разделе мы рассмотрим основные функциональные подгруппы, реа-лизованные в пространстве имен Sys, — объект Application, действия и при-вязки.

ПРИМЕЧАНИЕВ электронную документацию Atlas входит утилита для просмотра клиентских клас-сов, с помощью которой можно получить подробную информацию о классах, их членахи свойствах. Кроме того, имеется полный исходный код библиотеки. Локальную доку-ментацию Atlas можно загрузить по адресу http://atlas.asp.net.

Объект ApplicationКласс Sys._Application играет ключевую роль в среде Atlas. Каждый раз, когдав браузере загружается страница Atlas, создается экземпляр класса _Application,который присваивается объекту Sys.Application. В самом конце файла Atlas.js на-ходится следующая команда:

Sys.Application = new Sys._Application();

Page 173: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 7 3

После объявления всего кода JavaScript, входящего в библиотеку Micro-soft AJAX, файл Atlas.js создает объект, представляющий текущее приложениев браузере. Задача создания экземпляра приложения зарезервирована для Atlas;разработчики никогда не должны создавать дополнительные экземпляры класса.Application.

Члены класса Sys._ApplicationКласс Sys._Application наследует от Object и реализует два интерфейса: Sys.lType-DescriptorProvider и Sys.lCustomTypeDescriptor:

Sys._Application.registerSealedClass('Sys._Application',null,Sys.ITypeDescriptorProvider, Sys.ICustomTypeDescriptor);

Методы двух интерфейсов предоставляют упрощенный механизм рефлексиидля объектов Atlas JavaScript. Класс Sys._Application использует методы интер-фейсов для предоставления стандартизированного доступа к своим членам.

Класс Sys._Application поддерживает два события и один метод. Метод назы-вается findObject, а события — load и unload.

Поиск компонентов AtlasМетод findObject просматривает runtime-иерархию компонентов Atlas текущейстраницы в поисках компонента с заданным идентификатором. Метод имеет двавозможных прототипа:

Sys._Application.findObject(id);Sys._Application.findObject(id, context);

Первая перегруженная версия получает идентификатор искомого компонентаи просматривает всю иерархию от корневого узла. При задании аргумента context,отличного от null, поиск ограничивается поддеревом объекта context. Параметр idдолжен быть строковым, а параметр context — содержать объект Atlas. Методвозвращает объект с совпадающим идентификатором или null, если такой объектне найден.

Что собой представляет иерархия компонентов Atlas? Каждая страница Atlasсодержит разметку XML Script, сгенерированную элементом ScriptManager, и всесерверные элементы Atlas, задействованные в работе страницы. Минимальныйкод XML Script выглядит примерно так:

<script type="text/xml-script"><page xmlns:script="http://schernas.niicrosoft.coni/xnil-script/2005">

components /></page>

</script>

Содержимое тега <components> разбирается при загрузке страницы для со-здания runtime-иерархии компонентов Atlas. Как упоминалось ранее, для поискакомпонентов Atlas также может использоваться сокращенная запись $object(...).

Page 174: Microsoft ASP.NET 2.0 AJAX

1 7 4 Глава 5. Библиотека Microsoft AJAX

События жизненного цикла страницыПри первоначальной загрузке страницы Atlas происходит событие load, при об-работке которого клиентский код выполняет всю необходимую инициализацию.Важно заметить, что событие относится к жизненному циклу страницы, а неприложения. Таким образом, при каждом классическом возврате данных будетпроисходить новое событие load. Для возврата данных в стиле AJAX события негенерируются. Парное событие unload генерируется при выгрузке страницы.

Событие load происходит после полного завершения загрузки и инициализа-ции страницы Atlas. В страницах Atlas инициализацию рекомендуется выпол-нять при обработке события load (вместо события onload браузера). Таким обра-зом, только после получения события Atlas load можно с полной уверенностьюсчитать, что страница Atlas готова к взаимодействию с пользователем.

Событие unload происходит непосредственно перед тем, как runtime-средаAtlas освобождает страницу и все ее ресурсы. Для стабильной работы приложе-ния все операции зачистки следует выполнять в обработчике этого события (вме-сто события onunload браузера).

Следующий фрагмент показывает, как добавлять обработчики событий loadи unload на уровне сценария:

Application.1oad.add( 1 oadHandler);Application.unload.add(unloadHandler);

Код помещается в тег <script>, импортируемый в страницу. Еще более про-стой способ определения обработчиков load и unload основан на использованииготовых функций pageLoad и pageUnload. Эти функции являются глобальнымии вызываются без параметров:

<script type="text/javascript" language="Javascript">function pageLoadO{

alertC'Being loaded");}function pageUnloadO{

alertC'Being unloaded");}</script>

Декларативный интерфейс для Sys._ApplicationВ Atlas все, что делается посредством сценариев, также может делаться с приме-нением блоков XML Script. Этот принцип относится и к конфигурации объектаApplication. Вот как обработчик события load определяется в коде XML Script:

<script type="text/xml-script"><page xmlns:script="http://schernas.niicrosoft.coni/xnil-script/2005">

<components><application 1oad="MyPageLoad()"></application>

</components></page>

Page 175: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 7 5

</script><script type="text/javascript" language="Javascript">

function MyPageLoadO{alertC'Being loaded");

}</script>

Полный синтаксис тега XML Script <application> богаче, чем может показать-ся по предыдущему фрагменту:

application load="event handler" unload="event handler"><load>

<!-- действия --></load><unload>

<!-- действия --></unload>

</application>

В частности, он позволяет разработчикам задавать код, выполняемый привозникновении событий load и unload, на чисто декларативном уровне. Код обра-ботки следует по возможности сводить к последовательности действий. Как оп-ределять такие действия? И еще важнее — что собой представляют запрограм-мированные действия Atlas и как они программируются?

С точки зрения реализации действия являются компонентами Atlas, которыепредставляют команды, предназначенные для исполнения. Сначала мы поближепознакомимся с компонентами Atlas, а затем разберемся, как действия реализу-ются на декларативном уровне.

Компоненты AtlasТермином «компонент» обычно обозначается объект, предназначенный для по-вторного использования и способный взаимодействовать с другими объектамив контексте прикладной среды. С другой стороны, термин «элемент» обычнообозначает объект, который является специализированным компонентом. Глав-ной характеристикой, определяющей различия между элементами и компо-нентами, является пользовательский интерфейс (UI, User Interface). Компоненты,в отличие от элементов, не обладают пользовательским интерфейсом.

В большинстве прикладных сред, в том числе в .NET Framework и библиоте-ке Microsoft AJAX, компоненты и элементы наследуют от разных базовых клас-сов и, как следствие, находятся в изолированных ветвях иерархии наследования.

В Atlas иерархия компонентов начинается с корневого класса Sys.Component.Корневой класс элементов называется Control и принадлежит (кто бы мог поду-мать!) пространству имен Sys.UI. Сейчас мы поближе познакомимся с общимисвойствами компонентов, а позднее сосредоточимся на элементах.

Класс Sys.ComponentАбстрактный класс Sys.Component определяет ряд свойств и событий, общих длявсех компонентов прикладной среды Atlas. Свойства класса Sys.Component пере-числены в табл. 5.2.

Page 176: Microsoft ASP.NET 2.0 AJAX

1 7 6 Глава 5. Библиотека Microsoft AJAX

Таблица 5.2. Свойства класса Sys.Component

Свойство Описаниеbindings Возвращает привязки, принадлежащие компонентуdataContext Исходный объект, используемый в операциях привязки данных

(свойство доступно для чтения и записи)id Идентификатор, однозначно определяющий компонент (свойство

доступно для чтения и записи)isInitialized Указывает, прошел ли компонент инициализациюisUpdating Указывает, находится ли компонент в процессе пакетного обновления

У большинства компонентов Atlas имеются аналоги в модели DOM. Свойст-во id связывает компонент с элементом DOM, обладающим указанным иденти-фикатором. Свойство id также позволяет проводить поиск компонентов по имени.

var component = $object(id);

Функция $object предназначена для поиска компонентов в дереве Atlas.Класс Sys.Component содержит метод initialize, предназначенный для началь-

ной инициализации компонента. Базовая реализация метода ограничиваетсяпростым созданием экземпляра коллекции bindings. В производных классах спе-циализированные версии метода могут выполнять дополнительные операции.

Обнаружение изменений свойствКласс Sys.Component содержит встроенный механизм отслеживания измененийсвойств компонентов. При изменении свойства компонента генерируется собы-тие propertyChanged. Внутренний метод базового класса raisePropertyChanged по-зволяет производным компонентам генерировать событие propertyChanged, чтобыоповестить вызывающую сторону об изменении значения свойства. Например,реализация свойства компонента может выглядеть так:

this.set_MyProperty = function(value) {_myProperty = value;this.raisePropertyChanged("MyProperty");

}

В общем случае производные компоненты включают вызов raisePropertyChangedв метод set заданного свойства.

Пакетные обновленияВ классе Sys.Component также учтена возможность одновременного обновлениянескольких свойств. Чтобы свести к минимуму обновление экрана, можно при-казать объекту выполнить изменение свойств в пакетном режиме. Для этогообновления группируются между вызовами методов beginUpdate и endUpdate.На время незавершенной операции пакетного обновления значение свойстваisUpdating автоматически задается равным true.

В зависимости от специфики компонента пакетные обновления могут повы-сить быстродействие и свести к минимуму обновления экрана.

Page 177: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 7 7

Привязка данныхКомпоненты Atlas обладают встроенной поддержкой привязки данных. Свойст-во dataContext определяет источник данных, а в коллекции bindings хранится ин-формация о наборе привязок компонента.

В Atlas привязка представляет логическую, однонаправленную связь междуэлементом и компонентом. Связь соединяет источник данных компонента (свой-ство dataContext) с одним свойством целевого элемента.

Привязки подчиняются правилам наследования; это означает, что произ-водные компоненты наследуют родительский контекст данных, если только ихсвойству dataContext не будет задана другая коллекция. Привязка данных будетрассматриваться в главе 7.

Декларативные действияДекларативное программирование в Atlas встречается повсеместно и распростра-няется на все области программирования. Разработчик может не только сфор-мировать пользовательский интерфейс веб-страницы в виде тегов разметки, нои задать поведение страницы клиентской стороны объединением нескольких те-гов XML Script, каждый из которых содержит ссылку на блок кода JavaScript.Atlas выводит программирование на новый уровень, позволяя разработчикамзадавать на декларативном уровне действия — по крайней мере для таких стан-дартных задач, как вызов метода, задание свойства или инициирование воз-врата данных.

Базовым классом JavaScript для всех декларативных действий Atlas являетсяабстрактный класс с именем Sys.Action. Класс наследует от Sys.Component и реа-лизует интерфейс lAction:

Sys.Action.registerAbstractClass('Sys.Action', Sys.Component, Sys.IAction);

Реальные компоненты, производные от класса Action, связываются с собы-тиями и указывают, какая функция должна вызываться при возникновении тогоили иного события. К числу встроенных классов действий относятся Invoke-MethodAction, SetPropertyAction и PostBackAction.

Класс ActionВ табл. 5.3 перечислены свойства, определенные для класса Sys.Action и являю-щиеся общими для всех производных классов.

Как упоминалось ранее, действия связываются с событиями; события, в своюочередь, связываются с обработчиками. Может оказаться, что с одним событиемсвязана серия действий и обработчик. Что должно выполняться первым? Ответна этот вопрос зависит от свойства sequence. Допустимые значения свойстваsequence объединены в перечисляемый тип Sys.ActionSequence:

Sys.ActionSequence.BeforeEventHandler = GSys.ActionSequence.AfterEventHandler = 1

Значение определяет, когда должно выполняться действие: до или после об-работчика событий. По умолчанию используется значение BeforeEventHandler.

Page 178: Microsoft ASP.NET 2.0 AJAX

1 7 8 Глава 5. Библиотека Microsoft AJAX

Таблица 5.3. Свойства класса Sys.Action

Свойство ОписаниеeventArgs Свойство доступно только для чтения; возвращает аргумент, переданный

методу executeresult Свойство доступно только для чтения; возвращает значение, полученное

в результате выполнения метода performActionsender Свойство доступно только для чтения; возвращает владельца события,

инициировавшего действиеsequence Свойство доступно для чтения и записи; указывает, должно ли действие

выполняться до или после обработчиков события, инициировавшегодействие

target Свойство доступно для чтения и записи; указывает объект Atlas,являющийся целью действия

Класс Sys.Action также содержит два метода: execute и performAction. МетодperformAction никогда не должен вызываться напрямую, потому что он считаетсявнутренним методом. В полноценном объектно-ориентированном языке програм-мирования он, вероятно, был бы определен как защищенный (protected) метод.Метод performAction дает возможность производным классам выполнить те дей-ствия, для выполнения которых они проектировались.

С другой стороны, метод execute относится к открытому интерфейсу и позво-ляет выполнять действия управляющему коду. Метод сначала вычисляет вход-ные привязки действия, а затем выполняет конкретное действие, определяемоеклассом действия. В завершение метод вычисляет выходные привязки. Возвра-щаемое значение performAction сохраняется в переменной result.

ПРИМЕЧАНИЕПривязки представляют собой специальные однонаправленные связи, обеспечиваю-щие управление потоком данных между компонентами как на входе, так и на выходе.Мы вернемся к теме привязок позднее в этой главе.

Класс Invoke Met hod Act ionКласс InvokeMethodAction используется для вызова методов компонентов Atlas.Он не может использоваться для вызова методов JavaScript. Класс содержит двадополнительных поля: method и parameters.

Свойство method определяет имя метода, выполняемого для объекта, на кото-рый ссылается переменная target. Аргументы метода могут передаваться в полеeventArgs класса Action, а свойство sequence определяет, должен ли метод вызы-ваться до или после обработчиков событий.

В коллекции parameters могут передаваться входные аргументы вызываемогометода. В частности, коллекция parameters используется при постоянных дан-ных. Если ввод зависит от других свойств, используются привязки.

Page 179: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 7 9

Класс SetPropertyActionКласс SetPropertyAction предназначен для присваивания нового значения произ-вольному свойству компонента Atlas. Свойство property определяет имя задавае-мого свойства, а свойство value — присваиваемое значение. Наследуемые свойства(такие, как target и sequence) играют ту же роль, что и в уже описанном классеInvokeMethodAction. Если свойство target ссылается на объект или массив, свойст-во propertyKey задает ключ или индекс.

Действия могут связываться с событиями как на программном, так и на дек-ларативном уровне. Схема XML Script для класса действия выглядит так:

<setPropertyproperty="имя целевого свойства" sequence=" BeforeEventHandler\AfterEventHandler"target="объект, для которого вызывается метод" value="3tf34etfjfe"<@062>

</setProperty>

Дополнительные дочерние элементы могут задавать привязки для действияи участвующих компонентов.

Следующий пример страницы Atlas демонстрирует возможности класса Set-PropertyAction:

<html xmlns="http://www.w3.org/1999/xhtml" ><head>

<title>Actions</title></head>

<body><form id="forml" runat="server"><asp:ScriptManager ID="ScriptManagerl" runat="server" /><div>

<hl>SetProperty Action in action</hl><hr /><p>Message: <strong><span id="msg"></span></strong></p><p><input id="Buttonl" type="button" value="Click" /></p><hr />

</div></form>

<script type="text/xml-script"><page xmlns:script="http://schemas.microsoft.com/xml-script/2005">

<components><label id="msg" /><button id="Buttonl" click="DoSomething" >

<click><setProperty sequence="AfterEventHandler"

target="msg" property="Text" value="A new value..." /></click>

</button></components>

</page></script>

<script type="text/javascript">

Page 180: Microsoft ASP.NET 2.0 AJAX

1 8 0 Глава 5. Библиотека Microsoft AJAX

function DoSomethingO{

alertC'Believe it or not, I'm doing something...");}

</script></body></html>

Разметка HTML-страницы содержит клиентскую кнопку и тег <span>. Этидва элемента связываются с компонентами Atlas при помощи фрагмента кода XMLScript. А именно, тег <span> связывается с компонентом <label>, а тег <input> —с компонентом <button>. Соответствие устанавливается по значениям идентифи-каторов:

<components><label id="msg" /><button id="Buttonl" click="DoSomething" />

</components>

Как будет подробно объяснено позднее, компонент Atlas Button обладаетсвойством click, которое содержит ссылку на фрагмент кода JavaScript, выпол-няемого по щелчку пользователя. Помимо обработчика события, с событием ком-понента можно связать дополнительные действия:

<button id="Buttonl" click="DoSomething" ><click>

<setProperty sequence="AfterEventHandler"target="msg" property="Text" value="A new value..." />

</click></button>

Когда пользователь щелкнет на кнопке, строка "A new value..." будет присвое-на свойству Text компонента Atlas msg. Это действие будет выполнено после воз-врата управления событием JavaScript. Результат показан на рис. 5.2. В этомконкретном примере обработчик события JavaScript просто отображает окно со-общения. Пока окно сообщения остается активным, текст надписи не изменяет-ся. После того как окно сообщения будет закрыто, сигнализируя о завершенииобработки события, происходит обновление компонента Atlas msg.

Класс PostBackActionКласс PostBackAction немедленно выполняет классический возврат данных ASP.NET. Свойство eventArgument задает аргумент, передаваемый серверу. Свойствоtarget определяет имя клиентского компонента, который считается ответствен-ным за возврат данных.

Класс PostBackAction в конечном счете вызывает функцию doPostBack, лежа-щую в основе механизма возврата данных ASP.NET. Реализация метода perform-Action класса PostBackAction выглядит так:

this.performAction = function О { doPostBack(this.getjtargetО, this.get_eventArgument());

}

Page 181: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 8 1

Рис. 5.2. Связывание действий с обработчиком события click кнопки

Свойства eventArgument и target соответственно заполняют скрытые поляEVENTARGUMENT и EVENTTARGET запроса ASP.NET. Учтите, что вызов doPost-

Back не включается в страницы ASP.NET по умолчанию. Чтобы избежать ошиб-ки времени выполнения JavaScript Object Not Found (Объект не найден), необхо-димо либо включить в страницу серверный элемент, генерирующий этот кодавтоматически (например, LinkButton), либо написать его вручную. Пример:

<Й?Раде Language="C#" %><html xmlns="http://www.w3.org/1999/xhtml" ><head>

<title>PostBack Actions</title></head>

<script runat="server">void Page_Load(object sender, EventArgs e){

// Ensures that doPostBack is referenced in the pageClientScript.GetPostBackEventReference(this, " " ) ;

}void Buttonl_Click(object sender, EventArgs e){

Response.WriteCClicked");

</script>

<body><form id="form1" runat="server">

Page 182: Microsoft ASP.NET 2.0 AJAX

1 8 2 Глава 5. Библиотека Microsoft AJAX

<asp:ScriptManager ID="ScriptManagerl" runat="server" /><div>

<hl>PostBack Action in action</hl>

<span id="msg">Click here and see what happens!</span><hr />

<asp:Button runat="server" ID="Buttonl" enabled="false"onclick="Buttonl_Click" Text="Click" />

<hr /></div></form>

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><button id="Buttonl" /><label id="msg">

<behaviors><clickBehavior>

<click><postBack target="Buttonl" eventArgument="" />

</click></clickBehavior>

</behaviors></label>

</components></page>

</script></body></html>

Разметка HTML-страницы содержит тег <span> и заблокированную кнопкуотправки данных. Тег <span> отображается на элемент Atlas Label с поведениемclick (мы вернемся к теме клиентских аспектов поведения позднее в этой главе).Аспект поведения предоставляет событие Click и выполняет заданную последо-вательность действий каждый раз, когда пользователь щелкает на элементе. Дляприведенного выше кода XML Script страница будет выполнять возврат данныхкаждый раз, когда пользователь щелкает на теге <span>. Что произойдет потом?

Тег <postBack> назначает Button 1 исполнителем (executor) возврата данных.Другими словами, runtime-среда ASP.NET считает, что возврат данных был ини-циирован Buttonl. Соответственно ASP.NET будет проверять, существует ли эле-мент серверной стороны Buttonl, реализующий интерфейс IPostBackEventHandler.Если такой элемент не существует, возврат просто приведет к обновлению стра-ницы без других последствий. В противном случае будет выполнен код возвратаданных, связанный с элементом. В предыдущем примере Buttonl — простаякнопка отправки данных, созданная тегом <asp:Button>. С серверным событиемClick кнопки связан фрагмент кода:

<asp:Button runat="server" ID="Buttonl" enabled="false"onclick="Buttonl_Click" Text="Click" />

Page 183: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 8 3

<script runat="server">void Buttonl_Click(object sender, EventArgs e){

Response.Write("Clicked");}

</script>

Когда пользователь щелкает на тексте тега <span>, происходит возврат дан-ных с целевым элементом Button 1. В результате генерируется серверное событиеClick для элемента Button"!. Таким образом, класс PostBackAction позволяет кли-ентскому коду осуществлять возврат данных «от имени» практически любогосерверного элемента ASP.NET, даже если на стороне клиента этот элемент за-блокирован.

Для успешного использования класса PostBackAction необходимо учитыватьпару обстоятельств. Во-первых, проследите за тем, чтобы к странице была под-ключена функция JavaScript doPostBack. Это заведомо произойдет при вклю-чении в Page_Load следующего кода:

С1 ientScript.GetPostBackEventReference(this, " " ) ;

Во-вторых, свойство target класса PostBackAction должно ссылаться на компо-нент Atlas, который, в свою очередь, должен ссылаться на существующий эле-мент DOM. А это означает, что для инициирования возврата данных от имениButton 1 должен использоваться следующий блок XML Script:

<components><button ID="Buttonl" />

</components>

Поскольку реализация инициирует немедленный возврат данных серверу, дей-ствия, следующие за действием возврата, никогда не будут выполнены.

Другие компоненты и функциональныевозможностиБиблиотека Microsoft AJAX содержит ряд других компонентов, предоставляю-щих дополнительные возможности для разработчиков Atlas. Давайте кратко по-знакомимся с некоторыми из них, начиная со сценарной версии популярногоуправляемого класса .NET Framework — StringBuilder.

Операции со строкамиКласс Sys.StringBuilder наделяет страницы Atlas расширенными возможностямиобработки текста. Как нетрудно догадаться по имени, класс имитирует поведе-ние управляемого класса StringBuilder, определяемого в .NETG Framework.

При создании экземпляра объекта-построителя указывается исходный текст.Построитель сохраняет текст во внутреннем массиве, создавая новый элементдля каждой следующей присоединяемой строки.

Методы класса Sys.StringBuilder перечислены в табл. 5.4.

Page 184: Microsoft ASP.NET 2.0 AJAX

1 8 4 Глава 5. Библиотека Microsoft AJAX

Таблица 5.4. Методы класса Sys.StringBuilder

Метод Описаниеappend Присоединяет заданный текст к внутреннему массивуappendLine Вызывает метод append и присоединяет символ новой строкиclear Стирает текст, хранящийся в построителеisEmpty Проверяет, содержит ли построитель какой-либо текстtoString Возвращает содержимое массива в виде простой строки

Объект StringBuilder не работает с другими объектами, кроме строк, отлич-ных от null. Метод toString формирует текст с использованием метода join классамассива:

// _parts - внутренний массив, используемый для сохранения текстаthis.toString = function(delimiter) {

return _parts.join(delimiter || ' ' ) ;}

Класс Atlas String также дополнен методом format, имитирующим поведениеметода Format класса .NET Framework String:

// RuntimeVersion - глобальная переменная в Atlas.jsalert(String.format("Atlas version: {0}", RuntimeVersion));

Для определения заменителей в форматных строках используется синтак-сис {п}. Реальное значение, подставляемое на место заменителя, определяетсяn-м аргументом вызова метода format.

Класс Sys.TimerЭкземпляр класса Sys.Timer, размещенный на странице Atlas, генерирует событияс заданным интервалом. Класс имеет два свойства, доступных для чтения и запи-си — enabled и interval. Свойство enabled указывает, активен ли таймер в настоя-щее время; по умолчанию оно равно false. Свойство interval задает периодичностьвозникновения события tick. Интервалы задаются в миллисекундах. По умолча-нию свойство interval равно 1000 (одна секунда). Следующий фрагмент кода по-казывает, как производится программная настройка объекта таймера:

<script type="text/javascript" language="Javascript">var theTimer;function CreateTimerO{

theTimer = new Sys.TimerO;theTimer.initializeO;// Запуск таймераtheTimer.tick.add(OnTick);theTimer.set_enabled(true);

}function OnTickO{

// Чтобы избежать проблем с обработчиками tick,

Page 185: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 8 5

// можно блокировать таймер при входе в обработчик// и включать его заново при выходе.var builder = new Sys.StringBuiIder("");builder.appendLineC'The tick arrives every {0} milliseconds.");builder.appendC'Click CANCEL to stop the timer");var msg = String.format(builder.toStringO , theTimer.get_interval());var canContinue = confirm(msg);theTimer.set_enabled(canContinue);

}</script>

Чтобы запустить клиентский таймер, следует задать свойству enabled значе-ние true — вызовите метод set_enabled и передайте параметр true. Если потребует-ся проверить, активен ли таймер в настоящее время, вызовите метод get_enabled.

ПРИМЕЧАНИЕДля чтения свойств компонентов Atlas следует использовать методы getXXX, а дляприсваивания — методы setXXX, где XXX — имя свойства.

С компонентом Timer также можно работать на декларативном уровне с ис-пользованием следующей схемы XML Script:

<timerenabled="true|false"id-"идентификатор"interval-"интервал в миллисекундах" tick="обработчик события"/>

В главе 4 был представлен компонент TimerControl, предоставляющий те жевозможности. Чем отличаются эти два компонента?

Компонент Timer относится к числу компонентов Atlas клиентской стороны; этоозначает, что его событие tick является клиентским событием. Срабатывание тай-мера не приводит к возврату данных на сервер. С другой стороны, TimerControl —полноценный серверный элемент, используемый при разработке на стороне серве-ра. Соответственно, его экземпляр создается на стороне сервера, а в клиентскую стра-ницу внедряется код, осуществляющий возврат данных при истечении интервала.

Класс Sys.CounterКласс Sys.Counter работает как простой счетчик с функциями увеличения и умень-шения.

Программный интерфейс компонента описан в табл. 5.5.

Таблица 5.5. Члены класса Sys.Counter

Член класса ОписаниеcanDecrement Свойство указывает, возможно ли дальнейшее уменьшение счетчика

при его текущем значении и нижней границеcanIncrement Свойство указывает, возможно ли дальнейшее увеличение счетчика

при его текущем значении и верхней границепродолжение ■&

Page 186: Microsoft ASP.NET 2.0 AJAX

1 8 6 Глава 5. Библиотека Microsoft AJAX

Таблица 5.5 (продолжение)

Член класса Описаниеdecrement Уменьшает счетчикincrement Увеличивает счетчикlowerBound Нижняя граница счетчика (чтение и запись)upperBound Верхняя граница счетчика (чтение и запись)value Текущее значение счетчика (чтение и запись)

При вызове методов decrement и increment класс автоматически проверяет,допустимо ли новое значение счетчика, и принадлежит ли оно текущим грани-цам. Следующий фрагмент кода демонстрирует создание объекта Counter и егоиспользование для остановки таймера после 5 тактов:

<script type="text/javascript" language="Javascript">var trie-Timer;var theCounter;function Setup(){

// Подготовка таймера и счетчикаtheCounter = new Sys.CounterO;theCounter.set_value(0);theTimer = new Sys.TimerO ;theTimer.initialize();

// Запуск таймераtheTimer.tick.add(OnTick);theTimer.set_enabled(true);

}

// Обновление пользовательского интерфейса

$("msg").innerHTML = "Timer started...";

function OnTickO{

// Остановка таймера после 5 тактовif (theCounter.get_value() >5){

theTimer.set_enabled(false);

// Обновление пользовательского интерфейса$("msg").innerHTML = "Timer stopped...";alertC'Timer stopped");$("msg").innerHTML = "";

}theCounter.increment();

}</script>

В этом примере я использую обычный код JavaScript для вывода сообщенийчерез тег <span> с именем msg (рис. 5.3).

Page 187: Microsoft ASP.NET 2.0 AJAX

Основные компоненты 1 8 7

Рис. 5.3. Пример страницы Atlas с таймером и счетчиком

Привязки Atlas позволяют избавиться от лишнего кода JavaScript и ограни-читься стопроцентным использованием XML Script практически в любой ситуа-ции. Привязки будут более подробно рассмотрены далее в этой главе.

Класс Sys._DebugТакже стоит упомянуть класс Sys._Debug. Основные возможности этого классауже были описаны в главе 2. Экземпляр класса присваивается свойству debugобъекта DOM window:

window.debug = new Sys._Debug();

Отладочный объект DOM используется для проверки контрольных условий,выхода в отладчик и вывода трассировочного текста.

Класс Sys.Net.WebRequestРастущая популярность библиотек AJAX вообще и Atlas в частности в значи-тельной степени обусловлена внеполосными веб-запросами. Некоторые библио-теки AJAX предоставляют простой программный интерфейс на базе функцийдля выполнения таких вызовов, однако в Atlas используется объектно-ориенти-рованная подсистема, в центре которой находится класс WebRequest:

<script type="text/javascript">function sendRequest(url)

Page 188: Microsoft ASP.NET 2.0 AJAX

1 8 8 Глава 5. Библиотека Microsoft AJAX

{var request = new Sys.Net.WebRequestO;request.set_url(url);request.invokeO;

}</script>

Этот фрагмент показывает, как использовать класс Sys.Net.WebRequest длясоздания веб-запроса к заданному URL.

Класс WebRequest определяет свойство url для чтения и записи целевогоURL, а также свойство headers для включения строк заголовков в запрос. Такжеразработчик может задать приоритет (свойство priority) и тайм-аут (свойствоtimeoutlnterval) для завершения запроса. Для запросов типа POST тело задаетсясвойством body.

Класс WebRequest задействован во многих встроенных возможностях страницAtlas (см. главу 6), связанных с внеполосными вызовами.

Элементы пользовательского интерфейсаПодсистема пользовательского интерфейса Atlas содержит набор клиентских эле-ментов и аспектов поведения для взаимодействия с DOM. Клиентские элементыAtlas обладают более широкими возможностями, чем стандартные элементыHTML и соответствующие серверные элементы ASP.NET. Аспекты поведенияреализуют дополнительные возможности и эффекты пользовательского интер-фейса — перетаскивание, обработку задержки мыши и щелчков. К числу клиент-ских элементов Atlas относятся типичные веб-элементы (гиперссылки, кнопки,флажки, текстовые поля и надписи) и более сложные компоненты, такие каксписки, источники данных и т. д.

Клиентские элементыКлассы клиентских элементов Atlas в основном представляют собой «обертки»для элементов HTML. Они добавляют ряд новых функций к «родным» возмож-ностям элементов HTML и принимают полноценное участие в модели програм-мирования AJAX за счет поддержки действий, аспектов поведения и операцийпривязки данных.

Все клиентские элементы являются производными от класса Control и могутнастраиваться при помощи свойств и методов, лучше выражающих возможностии ожидаемое поведение инкапсулированных элементов HTML.

Элемент Atlas связывается ровно с одним элементом HTML — либо авто-номным элементом, либо корнем дерева элементов. Для создания экземпляраи использования клиентских элементов можно воспользоваться традиционнымкодом JavaScript или же прибегнуть к коду Atlas XML Script. В JavaScript экзем-пляр клиентской кнопки создается следующим образом:

// Объявление переменной и подключение кода JavaScriptvar button = new Web.UI.Button($("Buttonl"));button.click.add(DoSomething);

Page 189: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 8 9

Экземпляр элемента Button связывается с элементом HTML-страницы с именемButton 1. Следующий фрагмент кода XML Script приводит к тому же результату:

<script type="text/xml-script"><components>

<button id="Buttonl" click="DoSomething" />

</components></script>

Обратите внимание: все объекты, на которые вы ссылаетесь в XML Script,должны объявляться в секции <components>.

Общие члены элементовКак упоминалось ранее, все элементы Atlas наследуют от класса Sys.UI.Control.Класс содержит ряд свойств и методов, общих для всех клиентских элементов.Общие свойства класса перечислены в табл. 5.6.

Таблица 5.6. Свойства класса Sys.UI.Control

Свойство ОписаниеaccessKey Клавиша ускоренного доступа для элемента HTML, находящегося

под управлением элемента Atlas (чтение и запись)associatedElement Возвращает элемент DOM, связанный с элементом Atlasbehaviors Массив аспектов поведения, связанных с элементомcssClass Класс CSS для элемента HTML (чтение и запись)enabled Устанавливает или снимает блокировку со связанного элемента HTMLparent Родитель текущего элемента (чтение и запись)style Возвращает объект, представляющий текущий стиль элемента DOMtabIndex Индекс перебора элемента HTML, находящегося под управлением

элемента Atlas (чтение и запись)visibilityMode Режим видимости элемента DOM, связанного с элементом (чтение

и запись)visible Видимость элемента DOM, связанного с элементом (чтение и запись)

Свойства visible и visibilityMode управляют атрибутом CSS visibility. Если свой-ство visible истинно, значение visibilityMode игнорируется, а элемент просто ото-бражается на странице. Если свойство visible ложно, вы можете дополнительноуказать, должен ли браузер зарезервировать место, необходимое для отображе-ния элемента, и оставить его пустым либо просто пропустить элемент во времяпостроения страницы. Допустимые значения — Hide (используется по умолча-нию) и Collapse — объединены в перечисляемый тип Sys.UI.VisibilityMode. При зна-чении Hide (соответствует числу 0) браузер резервирует место для отображенияэлемента, а при значении Collapse (соответствует числу 1) браузер полностью иг-норирует элемент при построении.

Page 190: Microsoft ASP.NET 2.0 AJAX

1 9 0 Глава 5. Библиотека Microsoft AJAX

В табл. 5.7 перечислены методы, поддерживаемые всеми клиентскими эле-ментами Atlas.

Таблица 5.7. Методы класса Sys.UI.Control

Метод ОписаниеaddCssClass Добавляет класс CSS к связанному элементу HTMLcontainsCssClass Указывает, содержит ли связанный элемент HTML заданный класс CSSFocus Передает фокус ввода связанному элементу HTMLonBubbleEvent Метод переопределяется производными классами для обработки

событий, инициированных дочерними элементамиraiseBubbleEvent Пересылает события родителям элементаremoveCssClass Удаляет класс CSS из связанного элемента HTMLscrollIntoView Осуществляет прокрутку, чтобы связанный элемент попал в область

видимости браузераtoggleCssClass Переключает признак вхождения заданного класса CSS для связанного

элемента HTML в противоположное состояние

Давайте поближе познакомимся с клиентскими элементами Atlas и посмот-рим, какими свойствами и методами они обладают.

Элемент Sys.UI.ButtonЭлемент инкапсулирует произвольный элемент HTML и добавляет к нему под-держку обработки щелчков. Чаще всего элемент Button связывается с элементомHTML <input type=button>, однако он может быть связан с любой другой размет-кой HTML, поддерживающей щелчки мышью. Небольшой пример:

<form runat="server"><input id="TextBoxl" type="text" value="" /><input id="Buttonl" type="button" value="Set Value" /><span id="FakeButtonl">Click me</span>

</form>

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><textBox id="TextBoxl" /><button id="Buttonl">

<click><setProperty target="TextBoxl"

property="text" value="A new value..." /></click>

</button><button id="FakeButtonl">

<click><setProperty target="TextBoxl"

property="text" value="Another new value..." /></click>

Page 191: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 9 1

</button></components>

</page></script>

Страница содержит кнопку и тег <span>. В XML Script оба элемента HTMLсвязываются с элементом Atlas Button и наделяются аспектом поведения click.Когда пользователь щелкает на этих элементах, действие setProperty использует-ся для изменения содержимого текстового поля.

Класс Button поддерживает два дополнительных свойства argument и command,а также событие click. Свойство argument определяет параметр события click, а свой-ство command определяет логическую команду, инициируемую кнопкой.

Элемент Sys.UI.CheckBoxЭлемент инкапсулирует флажок HTML и добавляет к нему новое логическоесвойство checked, обозначающее состояние элемента:

<input id="TextBoxl" type="text" value="" /><input type="checkbox" id="CheckBoxl" />

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><textBox id="TextBoxl" /><checkBox id="CheckBoxl" click="Check" />

</components></page>

</script>

<script type="text/javascript">function CheckO{

if ($("CheckBoxl").checked)$("TextBoxl").value = "Checked";

else$("TextBoxl").value = "Unchecked";

}</script>

Щелчок на флажке обнаруживается обработкой события click либо на уровнедействий, либо в простом коде JavaScript.

Элемент Sys.UI.HyperLinkЭлемент инкапсулирует якорный тег HTML <а> и связывает его с моделью дек-ларативного программирования Atlas.

<а id="HyperLinkl">Click here</a>

<script type="text/xml-script">

<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">

Page 192: Microsoft ASP.NET 2.0 AJAX

1 9 2 Глава 5. Библиотека Microsoft AJAX

<components><hyperLink id="HyperLinkl" navigatellRL="..." />

</components></page>

</script>

Свойство navigateURL задает целевой URL гиперссылки, а событие click ис-пользуется для явной обработки щелчка. Обратите внимание: при обработке со-бытия click можно выполнить дополнительные операции, но не отменить перена-правление.

Элемент Sys.UI.ImageЭлемент Image инкапсулирует тег <img>, используемый для вывода графическихизображений. Он содержит ряд дополнительных свойств, в том числе alternateText,height, width и imageURL, но не предоставляет методов или событий. Чтобы создатьграфическую кнопку на стороне клиента, свяжите тег <img> с элементом Button.

Элемент Sys.UI.LabelЭлемент представляет тег <span> или любой другой тег, используемый в веб-стра-ницах для представления блока текста или разметки. Свойство text определяетотображаемый текст, а логическое свойство htmlEncode — режим вывода текста(кодирование HTML или отображение в исходном виде). По умолчанию текстне кодируется. Во внутреннем представлении при включенном режиме кодиро-вания текст задается свойством DOM innerText; в противном случае использует-ся свойство innerHTML.

Элемент Sys.UI.SelectЭлемент Select представляет список выбора — например, простой перечень илираскрывающийся список. Свойство selectedlndex определяет индекс текущего вы-деления (нумерация начинается с 0). Событие selectionChanged происходит приизменении выделения на странице пользователем. Пример:

<select id="SelectNumber"><option value="zero">Zero</option><option value="one">One</option><option value="two">Two</option>

</select>

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><select id="SelectNumber" selectionChanged="SelectionChanged" />

</components></page>

</script><script type="text/javascript">

function SelectionChangedO{

}</script>

Page 193: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 9 3

Другие свойства элемента Select относятся к функциям привязки данных.На веб-страницах списковые элементы часто связываются с динамически запол-няемыми коллекциями данных. Свойство data обеспечивает чтение и записьсвязанной коллекции данных. Свойства valueProperty и textProperty определяютпути данных к значению и тексту каждого объекта в списке. Мы вернемся к этимсвойствам позднее, когда будем рассматривать привязку данных в Atlas.

Элемент Sys.Ul.TextBoxЭлемент представляет собой «обертку» для элементов ввода HTML типа text. Онявляется производным от промежуточного класса InputControl, который, в своюочередь, является производным от Control и содержит одно дополнительноесвойство text.

Элемент не содержит методов и событий, но может участвовать в автомати-ческой проверке данных на стороне клиента; при этом используются членыродительского класса InputControl, которые будут рассматриваться в следующемразделе.

ПРИМЕЧАНИЕКак вы, возможно, заметили, элементы Atlas не содержат свойств и методов для явногозадания визуальных атрибутов — таких, как цвет фона, тип фона или шрифт. Эти и дру-гие графические свойства определяются в классах CSS, для назначения и управлениякоторыми используются методы базового класса Control.

Элементы проверки данныхПроверка данных — одна из самых распространенных операций, выполняе-мых веб-приложениями на стороне клиента перед отправкой форм на сервер.ASP.NET Atlas определяет ряд элементов с декларативными правилами, кото-рые убеждаются в том, что пользователь ввел правильные значения в связанныеэлементы.

Проверка данных применима ко всем элементам Atlas, производным от базово-го класса InputControl. Типичным примером элемента ввода с проверкой данныхявляется элемент TextBox. В табл. 5.8 перечислены члены, определяемые в классеInputControl.

Таблица 5.8. Свойства класса Sys.UI.InputControl

Свойство ОписаниеisInvalid Указывает, является ли текущее значение, введенное в поле,

недействительнымvalidators Возвращает список проверочных элементов Atlas, связанных

с элементом вводаvalidationMessage Возвращает сообщение об ошибке от первого нарушенного

правила проверки данныхvalidated Выдает событие после проверки данных

Page 194: Microsoft ASP.NET 2.0 AJAX

1 9 4 Глава 5. Библиотека Microsoft AJAX

Все проверочные элемент Atlas наследуют от класса Validator. Класс определя-ет два базовых свойства: islnvalid и errorMessage. Первое возвращает состояниеэлемента, отслеживаемого проверочным элементом, а второе — сообщение обошибке, которое выдается в случае недопустимого ввода. Кроме того, в классеValidator определяется абстрактный метод с именем validate, переопределяемыйпроизводными классами для реализации специализированного поведения припроверке. Связь между проверочными элементами Atlas и элементами вводаHTML устанавливается декларативно в коде XML Script. Впрочем, базовый классValidator также содержит метод setOwner для программного присоединения про-верочного элемента к элементу ввода. Задача решается включением экземплярав коллекцию validators элемента ввода:

var textBoxl = $("TextBoxl").control;var validator = new Sys.UI.RequiredFieldValidatorO ;validator.set_errorMessage("Must enter a value.");textBoxl.get_validators().add(validator);

Как упоминалось ранее, все элементы ввода поддерживают событие validated,происходящее в конце проверки. Обработчик события устанавливается на про-граммном уровне:

textBoxl.validated.add(onPostValidation);

Обработчик представляет собой фрагмент кода JavaScript с фиксированнымпрототипом:

<script type="text/javascript">function onPostValidation(sender, eventArgs){

// sender references the input controlif (sender.get_islnvalid()){

alert(sender.get_validationMessage());sender.focusO;

}}

</script>

Обработчик validated обычно добавляется в функции pageLoad. Событие vali-dated происходит в конце проверки. Как правило, процесс проверки инициирует-ся некоторым действием пользователя — скажем, при выходе из поля или щелчкеза пределами элемента. На программном уровне проверка запускается чтениемсвойства islnvalid элемента ввода:

// Код связывается с событием onclick клиентской кнопкиfunction triggerValidation О{

var invalidValue = $("TextBoxl").control.get_islnvalid();if (invalidValue)

alertC'Contents of TextBoxl is INVALID");else

alertC'All right!");}

Page 195: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 9 5

ВНИМАНИЕОпытные веб-разработчики знают, что проверка на стороне клиента еще не гарантиру-ет правильности данных, отправляемых на сервер. Например, в браузере может бытьотключена поддержка JavaScript, или злонамеренный пользователь мог обойти кли-ентский сценарий и специально сгенерировать вызов с потенциально вредоноснымиданными. Любое серьезное веб-приложение содержит уровень проверки данных, на ко-тором объединяются проверки на стороне клиента и сервера. Классические серверныеэлементы ASP.NET предоставляют функции проверки данных, у которых контроль настороне клиента является необязательным. ASP.NET Atlas предоставляет набор кли-ентских элементов для быстрого выполнения проверки. Никогда не полагайтесь толь-ко на эти элементы, если хотите быть уверены в том, что до сервера добралисьдействительные данные.

Заранее определенные элементы проверки данных проверяют, что поле вводане осталось пустым, что значения заданного типа входят в нужный диапазон илипроходят проверку по регулярному выражению.

Элемент Sys.UI.RequiredFieldValidatorЭлемент проверяет, не остался ли связанный с ним элемент пустым. Если вве-денные данные отсутствуют, элемент сбрасывает внутренний флаг и возвраща-ет сообщение об ошибке. Поведение элемента жестко запрограммировано в ме-тод validate:

this.validate = function(value) {if (lvalue) {

return false;}if (String.isInstanceOfType(value)) {

if (value.length == 0) { return false;

}}return true;

}

Как видно из листинга, метод validate получает значимые данные из отслежи-ваемого элемента в аргументе и выполняет свою специализированную проверку.Отслеживаемый элемент знает о существовании связанных элементов проверкии вызывает их последовательно, передавая значение, которое он считает значи-мым. Рассмотрим пример использования RequiredFieldValidator с текстовым полем.

Допустим, на странице имеется текстовое поле с близлежащим тегом <span>.Тег <span> предназначен для вывода признака недопустимых символов в поле — как правило, это символ «звездочка» (*).

<input id="TextBoxl" type="text" /><span id="TextBoxl_Validatorl" style="color: red">*</span>

А вот как будет выглядеть код XML Script:<page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><textBox id="TextBoxl">

Page 196: Microsoft ASP.NET 2.0 AJAX

1 9 6 Глава 5. Библиотека Microsoft AJAX

<validators><requiredFieldValidator

errorMessage="You can't leave this field empty." /></validators>

</textBox><validationErrorLabel id="TextBoxl_Validatorl"

associatedControl="TextBoxl" />

</components></page>

Сначала необходимое количество элементов проверки включается в секцию<validators> элемента TextBox. Затем добавляется элемент <validationErrorLabel>,у которого атрибут id ссылается на элемент DOM, представляющий признакошибки в элементе ввода. Сообщение об ошибке элемента проверки становитсявсплывающей подсказкой для признака ошибки, как показано на рис. 5.4. Когдатекстовый элемент назначается признаком ошибки, ASP.NET Atlas автоматиче-ски скрывает его и отображает только при наличии обнаружении ошибок.

Рис. 5.4. Элемент RequiredFieldValidator в действии

Элемент Sys.UI.RangeValidatorЭлемент проверяет, принадлежит ли введенное значение к заданному интервалу.Определяемый для него метод validate работает следующим образом:

this.validate = function(value) {if (value && value.length) {

return ((value <= jjpperBound) && (value >= _lowerBound));}return true;

}

Page 197: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 9 7

Элемент позволяет разработчику определять границы интервала при помощипары новых числовых свойств lowerBound и upperBound:

<textBox id="TextBoxl"><validators>

<rangeValidator lowerBound="l" upperBound="10"errorMessage="Values allowed between 1 and 10." />

</validators></textBox>

Как упоминалось ранее, поведение одного элемента ввода может зависеть откомбинации нескольких проверочных элементов.

Элемент Sys.UI.RegexValidatorЭлемент проверяет, соответствует ли введенное значение заданному регулярномувыражению. Регулярное выражение определяется в виде объекта JavaScript RegExp,доступного через свойство regex. Метод validate реализуется следующим образом:

this.validate = function(value) {if (value && value.length) {

var matches = _regex.exec(value);return (matches && (matches[0] == value));

}return true;

}

Пример использования элемента на веб-странице:<textBox id="TextBoxl">

<validators><regexValidator regex="/\(\d{3}$\)(\ )\d{3}$-\d{4}$/"

errorMessage="Phone number in the format '(xxx) xxx-xxxx'." /></validators>

</textBox>

Элемент Sys.Ul.TypeValidatorЭлемент проверяет, относится ли значение к заданному типу. Тип JavaScript, ис-пользуемый при проверке, задается при помощи свойства type:

<textBox id="TextBoxl"><validators>

<typeValidator type="Number" errorMessage="Enter a number." /></validators>

</textBox>

Приведенный фрагмент показывает, как настроить элемент TypeValidator в веб-странице Atlas.

Элемент Sys.UI.CustomValidatorЭлемент CustomValidator позволяет разработчику написать собственный код провер-ки входных данных. В его свойстве validateValue указывается функция JavaScript,которая должна вызываться при проверке.

<textBox id="TextBoxl"><validators>

<requiredFieldValidator errorMessage="Required field." />

Page 198: Microsoft ASP.NET 2.0 AJAX

1 9 8 Глава 5. Библиотека Microsoft AJAX

<customValidator validateValue="onValidateValue"errorMessage="Enter a valid color." />

</validators></textBox>

В этом фрагменте содержимое поля ввода проверяется пользовательскойфункцией JavaScript onValidateValue. Пример проверочной функции обратноговызова:

function onValidateValue(sender, eventArgs){

var colors = [ 'Red', 'Blue', 'Green', 'White'];var valid = colors.contains(eventArgs.get_value());eventArgs.set_isValid(valid);

}

Функция получает два аргумента. Аргумент sender обозначает элемент, ини-циировавший вызов функции. Аргумент eventArgs представляет собой объекттипа CustomValidationEventArgs. Объект обладает двумя свойствами: value и isValid.Пользовательская функция выполняет все необходимые проверки свойстваvalue, а затем соответствующим образом задает значение логического свойстваisValid.

Группы проверки данныхНекоторые элементы ввода на страницах ASP.NET могут объединяться в группыпроверки данных. В таких случаях результат общей проверки считается истин-ным только в том случае, если все сгруппированные элементы ввода содержатдействительные данные. Таким образом, разработчик может разбить все элемен-ты ввода, находящиеся на странице, на логические группы и проверять их по от-дельности. В Atlas группировка элементов ввода осуществляется при помощикомпонента <validationGroup>:

<validationGroup id="Groupl"><associatedControls>

<reference component="TextBoxl" /><reference component="TextBox2" />

</associatedControls></validationGroup>

Проверка группы элементов осуществляется методом isValid объекта Validation-Group:

<script type="text/javascript">function validateGroupK){

var group = $object("Groupl");var invalidValue = !group.get_isValid();if (invalidValue)

alertC'Contents of Groupl are INVALID");else

alertC'All right!");} </script>

Page 199: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 1 9 9

Объект группы проверки является объектом Atlas, поэтому для его получе-ния используется функция $object. Выполнение приведенного фрагмента кодаJavaScript обычно инициируется событием onclick клиентской кнопки.

Аспекты поведения клиентской стороныКак было показано в главе 4, аспекты поведения представляют собой особыекомпоненты, используемые для связывания фрагментов сценарного кода с элемен-тами HTML. Серверные расширители (см. главу 4) предназначены для расшире-ния клиентского поведения разметки, сгенерированной серверными элементами.Клиентские аспекты поведения, о которых речь пойдет в этом разделе, находятсяпод контролем клиентского сценарного кода, а их присоединение и отсоедине-ние осуществляется исключительно средствами JavaScript.

ПРИМЕЧАНИЕКонечной целью, как серверных расширителей, так и клиентских аспектов поведения,является расширение возможностей элементов HTML. Клиентские аспекты поведенияопределяют фрагмент кода JavaScript, который перехватывает некоторые клиентскиесобытия и обрабатывает их особым образом. Для определения клиентского аспектаповедения потребуется код JavaScript или XML Script. Серверный расширитель гене-рирует сценарный код и XML Script для привязки сценарного кода к событиям кли-ентской стороны. Клиентский код при этом не обязан соответствовать клиентскомуаспекту поведения. Другое различие заключается в том, что серверные расширителирасширяют только разметку HTML конкретного набора серверных элементов. Если выотдаете предпочтение серверо-центрической модели программирования Atlas, сначаларассмотрите возможность применения серверных расширителей.

Клиентские аспекты поведения представляют собой компоненты, производ-ные от класса Behavior и активизируемые клиентскими событиями — такими, какперемещения мыши, нажатия клавиш, срабатывания таймера и события DOM.Активизированный аспект поведения может делать практически все что угодно:обновлять свойства, запускать анимацию, реализовывать операции перетаскива-ния и т. д.

С одним элементом HTML может быть связано несколько аспектов пове-дения; один аспект поведения может быть связан с несколькими элементами.В среде Atlas определяется несколько встроенных клиентских аспектов поведе-ния, которые будут описаны в оставшейся части этого раздела.

AutoCompleteBehaviorАвтозаполнение расширяет возможности элементов TextBox и автоматическипредлагает пользователю возможные варианты при вводе данных в поле. Данныйаспект поведения представлен классом Sys.UI.AutoCompleteBehavior. При присоеди-нении к элементу TextBox этот аспект сохраняет текст, введенный пользователем,и посылает запрос сопутствующей веб-службе. Вызванный метод веб-службы воз-вращает список предлагаемых вариантов, которые упорядочиваются в раскры-вающийся список. Пользователь может быстро выбрать нужный текст вместотого, чтобы вводить его полностью.

Page 200: Microsoft ASP.NET 2.0 AJAX

2 0 0 Глава 5. Библиотека Microsoft AJAX

Обычно аспект поведения присоединяется к элементу TextBox через коллек-цию behaviors.

<asp:TextBox ID="CustomerName" runat="server" />

А вот что можно сделать на XML Script:<textBox id="CustomerName">

<behaviors><autoComplete minimumPrefixLength="l"

servicellRL="Suggestions.asmx"serviceMethod="GetSuggestions">

</autoComplete></behaviors>

</textBox>

Чтобы расширить текстовое поле функцией автозаполнения, вы сначала со-здаете (или находите) веб-службу, содержащую метод со следующей сигнатурой:

public string[] MethodName(string prefix, int count);

Имя веб-метода выбирается произвольно. Аргумент prefix определяет текст,введенный пользователем до настоящего момента. На основании анализа вводаметод возвращает предлагаемые варианты. Аргумент count задает максимальноеколичество возвращаемых вариантов. На рис. 5.5 показан эффект выполненияпредыдущего фрагмента для веб-службы suggestions.asmx, созданной в главе 4 для расширителя автозаполнения.

Рис. 5.5. Аспект поведения AutoCompleteBehavior в действии

Класс AutoCompleteBehavior дополняется рядом дополнительных свойств. Этисвойства перечислены в табл. 5.9.

Page 201: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 0 1

Веб-служба вызывается в процессе ввода данных в поле, расширенном пове-дением автозаполнения. Такая архитектура может породить большое количествозапросов. Чтобы количество асинхронных запросов оставалось под контролем,аспект поведения гарантирует, что между двумя последовательными обновления-ми пройдет заданное количество миллисекунд.

Таблица 5.9. Свойства класса AutoCompleteBehavior

Свойство ОписаниеcompletionInterval Интервал между двумя последовательными обновлениями

списка предлагаемых вариантов в миллисекундах;по умолчанию равен 1000 (чтение и запись)

completionList Блочный элемент, используемый для вывода перечняпредлагаемых вариантов (чтение и запись)

completionSetCount Максимальное количество предлагаемых вариантов, запрашиваемоеаспектом поведения (чтение и запись). Задает значение поумолчанию для параметра count веб-метода

minimumPrefixLength Минимальное количество символов, которые должны бытьвведены пользователем, чтобы аспект поведения попыталсяполучить список предлагаемых вариантов от веб-службы(по умолчанию 3)

serviceMethod Имя веб-метода (чтение и запись)serviceURL URL веб-службы, используемой для получения предлагаемых

вариантов (чтение и запись)

Стиль раскрывающейся панели до определенной степени находится под контро-лем разработчика. Используя свойство completionList, можно выбрать блочныйэлемент с предлагаемыми вариантами (обычно тег <div>). Однако большинствографических свойств элемента переопределяется аспектом поведения в соответ-ствии со свойствами текстового поля. Из свойств, которые можно изменять, наи-больший интерес представляет шрифт:

<div style="font-family:verdana;font-size:8pt;" id="Div1" />

Если присоединить этот тег <div> к аспекту поведения через свойство comp-letionList, предлагаемые варианты будут выводиться шрифтом Verdana.

ClickBehaviorКласс ClickBehavior добавляет семантику обработки щелчков к различным элемен-там HTML. Он выявляет событие DOM onclick связанного элемента и выполняетобработчики событий, определенные пользователем, и действия Atlas. В аспектеповедения определяется единственное событие click.

Обычно поведение click используется только с элементами HTML, не обла-дающими собственным синтаксисом обработки щелчков. Например, его не стоитиспользовать с кнопкой, потому что это лишь добавит излишней сложности

Page 202: Microsoft ASP.NET 2.0 AJAX

2 0 2 Глава 5. Библиотека Microsoft AJAX

элементу. С другой стороны, для добавления поддержки щелчков к тегу <span>без click не обойтись. Рассмотрим следующий фрагмент кода с надписью и кноп-кой:

<input type="button" id="Buttonl" value="Click" /><br /><asp:Label runat="server" ID="Label1" Text="Click me too" />

В странице Atlas щелчки на обоих элементах можно обрабатывать следую-щим образом:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><label id="Labell">

<behaviors><clickBehavior click="ClickTheLabel" />

</behaviors></label><button id="Buttonl" click="ClickTheButton" />

</components></page></script>

<script type="text/javascript">function ClickTheButtonO{

alertC'Believe it or not, you clicked the button...");}function ClickTheLabel(){

alertC'Believe it or not, you clicked the label...");}

</script>

Обработчик JavaScript для события щелчка на кнопке определяется при по-мощи атрибута click элемента Button. Щелчки на надписи обрабатываются с ис-пользованием компонента clickBehavior.

Обратите внимание: в данном случае ClickTheLabel является глобальной функ-цией JavaScript. Действия Atlas также можно указать в качестве потомков эле-мента <clickBehavior>.

HoverBehaviorКомпонент HoverBehavior активизируется тогда, когда указатель мыши задержи-вается над элементом HTML. При входе указателя мыши в ограничивающийпрямоугольник элемента генерируется событие hover, а при выходе из него — событие unhover. Кроме того, свойство unhoverDelay позволяет отложить выдачусобытия unhover на заданное количество миллисекунд. По умолчанию задерж-ка равна 0, но если она задана, то позволяет скрыть лишние пары событийunhover/hover, если пользователь многократно выходит и входит в одну областьза короткий период времени.

Page 203: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 0 3

Для примера рассмотрим элемент-кнопку Button 1. Следующий фрагмент кодавызывает и удаляет всплывающую подсказку при перемещении указателя мышинад кнопкой:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><button id="Buttonl">

<behaviors><hoverBehavior hover="SetTooltip"

unhover="ResetTooltip" /></behaviors>

</button></components>

</page></script><script type="text/javascript">

function SetTooltipO{

$("Buttonl").title = "You're on top of the button";}function ResetTooltipO{

$("Buttonl").title = "";}

</script>

Если подсказка не изменяется в зависимости от условий времени выполне-ния, лучше воспользоваться внутренним флагом, чтобы свойство DOM title неприходилось изменять при каждом входе и выходе в область кнопки.

PopupBehaviorКомпонент PopupBehavior преобразует одиночный элемент DOM в элемент верхне-го уровня, отображаемый поверх остальных элементов страницы (всплывающийэлемент). В общем случае поведение PopupBehavior может быть связано с любымэлементом DOM. Впрочем, эта возможность не имеет особого смысла для другихэлементов, кроме блочных — таких, как теги <div> или элементы ASP.NET Panel.

ПРИМЕЧАНИЕТипичная ситуация с использованием других элементов, кроме блочных, — необходи-мость вызова временного текстового поля, когда пользователь щелкает в заданном мес-те или перемещает мышь над активной зоной. Впрочем, как было показано в главе 4,расширители HoverMenu и Popup способны прекрасно справиться с этой задачей с ми-нимальными усилиями с вашей стороны. Проблема даже не в том, чтобы отобразитьэлемент DOM в режиме наложения, а в добавлении кода для задания свойств целевогоэлемента. С расширителями этот код достается «бесплатно». С другой стороны, рас-ширитель Atlas Popup, упоминавшийся в главе 4, не связывается с клиентским пове-дением Popup, о котором идет речь. Лучшая ситуация для применения клиентскогоповедения Popup без написания кода — отображение расширенных всплывающих под-сказок (об этом чуть позже).

Page 204: Microsoft ASP.NET 2.0 AJAX

2 0 4 Глава 5. Библиотека Microsoft AJAX

Класс PopupBehavior обладает четырьмя свойствами, перечисленными в табл. 5.10.

Таблица 5.10. Свойства класса PopupBehavior

Свойство Описание

parentElement

positioningMode

X

Y

Элемент DOM, используемый для позиционирования (чтениеи запись). Если говорить более абстрактно, parentElementуказывает на элемент DOM, являющийся целью Popup-поля

Якорная точка, используемая для вычисления позиции Popup-поля (чтение и запись). Допустимые значения объединеныв перечисляемый тип PositioningMode

Горизонтальное смещение относительно якорной точки, заданнойсвойством positioningMode (по умолчанию 0)

Вертикальное смещение относительно якорной точки, заданнойсвойством positioningMode (по умолчанию 0)

Позиция Popup-поля по отношению к родительскому элементу выражаетсязначениями перечисляемого типа PositioningMode, перечисленными в табл. 5.11.

Таблица 5 .11 . Перечисляемый тип PositioningMode

Значение Описание

Absolute Всплывающий элемент располагается в левом верхнем углуродительского элемента и накрывает его полностью или частичнов зависимости от относительных размеров (режим используетсяпо умолчанию). Соответствует числовому значению 0

Center Центр всплывающего элемента совмещается с центромродительского элемента. В этом случае всплывающий элементможет полностью закрывать родительский. Соответствуетчисловому значению 1

BottomLeft Всплывающий элемент располагается у нижней границыродительского элемента и стыкуется с левым краем.Соответствует числовому значению 2

BottomRight Всплывающий элемент располагается у нижней границыродительского элемента и стыкуется с правым краем.Соответствует числовому значению 3

TopLeft Всплывающий элемент располагается у верхней границыродительского элемента и стыкуется с левым краем.Соответствует числовому значению 4

TopRight Всплывающий элемент располагается у верхней границыродительского элемента и стыкуется с правым краем.Соответствует числовому значению 5

Page 205: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 0 5

Следующий фрагмент кода показывает, как определяется всплывающий эле-мент:

<div id="RichTooltip" style="display:none; border: solid 1px; ">This block of markup was originally inserted in the page as a DIV tag.It was then transformed into a popup element using the PopupBehaviorcomponent.

</div><input type="button" id="Button1" value="I’m the target of the popup" />

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><control id="RichTooltip">

<behaviors><popupBehavior id="popupBehaviorl"

parentElement="Buttonl" /></behaviors>

</control><button id="Buttonl" click="ManagePopup" />

</components></page>

</script>

Связывание всплывающего элемента с родительским элементом было лишьпервым шагом. Теперь необходимо найти удобный способ отображения или скры-тия всплывающего элемента. Для этой цели используются методы show и hideкласса PopupBehavior. Функция JavaScript ManagePopup отображает и скрываетвсплывающее поле, когда пользователь щелкает на кнопке (рис. 5.6).

<script type="text/javascript">var _popupDisplayed = false;function ManagePopupO{

var popup = $object("popupBehaviorl");if (_popupDisplayed)

popup.hideO;else

popup.showO;_popupDisplayed = !_popupDisplayed;

}</script>

Пример позволяет увидеть, как выбор режима позиционирования из перечис-ляемого типа PositioningMode влияет на размещение элемента. Чтобы задать ре-жим позиционирования на программном уровне, достаточно включить в функ-цию ManagePopup следующий фрагмент:

var pos = $("PositionModeList").selectedlndex;popup.set_positioningMode(pos);

Предполагается, что страница содержит раскрывающийся список с именемPositionModeList.

Page 206: Microsoft ASP.NET 2.0 AJAX

2 0 6 Глава 5. Библиотека Microsoft AJAX

Рис. 5.6. Отображение блока пользовательского интерфейса при щелчке на кнопке

Объединяя аспекты поведения PopupBehavior и HoverBehavior, можно реа-лизовать удобные, полнофункциональные всплывающие подсказки (рис. 5.7).Пример:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><control id="RichTooltip">

<behaviors><popupBehavior id="popupBehaviorl"

parentElement="Buttonl"positioningMode="BottomLeft" />

</behaviors></control><button id="Buttonl">

<behaviors><hoverBehavior hover="SetTooltip"

unhover="ResetTooltip" /></behaviors>

</button></components>

</page></script>

<script type="text/javascript">

Page 207: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 0 7

function SetTooltip()

{

$object("popupBehavior1").show();

}

function ResetTooltip()

{

$object("popupBehavior1").hide();

}

</script>

Рис. 5.7. Реализация подсказок с использованием аспектов поведения Atlas

Целевой элемент (в данном случае кнопка) связывается с обоими аспектами,PopupBehavior и HoverBehavior. Мы назначаем кнопку родителем всплывающегоэлемента, а затем используем события hover и unhover для отображения и скры-тия всплывающего элемента. В данном примере для отображения и скрытия ис-пользуется код JavaScript. Излишне говорить, что вместо него также можно вос-пользоваться декларативными действиями:

<button id="Buttonl"><behaviors>

<hoverBehavior><hover>

<invokeMethod target="popupBehaviorl" method="show" />

Page 208: Microsoft ASP.NET 2.0 AJAX

2 0 8 Глава 5. Библиотека Microsoft AJAX

</hover><unhover>

<invokeMethod target="popupBehaviorl" method="hide" /></unhover>

</hoverBehavior></behaviors>

</hoverBehavior>

OpacityАспект поведения Opacity — простой компонент, позволяющий затушевать любойэлемент DOM, с которым он связан. Учтите, что для работы данного аспектав страницу необходимо включить сценарий atlasuiglitz.js:

<atlas:ScriptManager ID="ScriptManagerl" runat="server"><Scripts>

<asp:ScriptReference ScriptName="AtlasllIGlitz" /></Scripts>

</asp:ScriptManager>

Допустим, имеется панель ввода следующего вида:

<asp:TextBox ID="TextBoxl" runat="server"></asp:TextBox><br /><asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><br /><input type="button" id="Buttonl" value="Start ..." />

Если кнопка запускает продолжительную операцию, некоторые элементыстоит затушевать — тем самым вы дадите пользователю понять, что дальнейшиедействия от него не ожидаются. Желаемого эффекта можно добиться при помо-щи поведения Opacity:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><button id="Buttonl" click="StartTask">

<behaviors><opacity id="opacityBehaviorl" />

</behaviors></button><textBox id="TextBoxl">

<behaviors><opacity id="opacityBehavior2" />

</behaviors></textBox><textBox id="TextBox2">

<behaviors><opacity id="opacityBehavior3" />

</behaviors></textBox>

</components></page>

</script>

<script type="text/javascript">

function StartTask()

Page 209: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 0 9

{// Задайте значение 1, чтобы вернуться к прежнему виду$object("opacityBehaviorl").set_value(0.3);$object("opacityBehavior2").set_value(0.3);$object("opacityBehavior3").set_value(0.3);

}</script>

Помните, что аспект поведения Opacity является чисто графическим инстру-ментом. Он просто применяет графический фильтр к части экрана, занимаемойэлементом DOM. Даже затушеванный элемент DOM остается доступным дляввода. Возможно, Opacity стоит использовать в сочетании с другими фрагмента-ми сценарного кода или просто для реализации графических эффектов.

FloatingBehaviorКомпонент FloatingBehavior преобразует подмножество элементов DOM в плаваю-щую область, которая может перетаскиваться мышью. Он является клиентскиманалогом элемента DragPanelExtender, описанного в главе 4. Код, сгенерированныйрасширителем, точно совпадает с кодом, внедряемым напрямую с использова-нием аспекта FloatingBehavior. В конечном итоге выбор между DragPanelExtenderи FloatingBehavior зависит от личных предпочтений — склонности к серверо-цен-трической или клиенто-центрической разработке.

Чтобы использовать класс FloatingBehavior, необходимо явно импортироватьв страницу сценарий atlasuidragdrop.js (это одна из важных подробностей, кото-рую от вас скрывает расширитель).

<atlas:ScriptManager ID="ScriptManagerl" runat="server"><Scripts>

<asp:ScriptReference ScriptName="AtlasUIDragDrop" /></Scripts>

</asp:ScriptManager>

Допустим, у вас имеется веб-страница с двумя панелями:<asp:Panel ID="CustomersPanelContent" runat="server">

<asp:Panel ID="CustomersPanelHandle" runat="server">

</asp:Panel><asp:Panel ID="CustomersPanel" runat="server">

</asp:Panel></asp:Panel>

<asp:Panel ID="EmployeesPanelContent" runat="server"><asp:Panel ID="EmployeesPanelHandle" runat="server">

</asp:Panel><asp:Panel ID="EmployeesPanel" runat="server">

</asp:Panel></asp:Panel>

Page 210: Microsoft ASP.NET 2.0 AJAX

2 1 0 Глава 5. Библиотека Microsoft AJAX

Следующий фрагмент кода XML Script позволяет перетаскивать мышью всесодержимое панелей:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><control id="EmployeesPanelContent">

<behaviors><floatingBehavior handle="EmployeesPanelHandle" />

</behaviors></control><control id="CustomersPanelContent">

<behaviors><floatingBehavior handle="CustomersPanelHandle" />

</behaviors></control>

</components></page>

</script>

Смысл сценария вполне прямолинеен. Мы определяем панели как компо-ненты Atlas при помощи элемента <control>, а затем связываем их с поведениемFloatingBehavior. Свойство handle обозначает элемент DOM, используемый в ка-честве манипулятора для перемещения панелей. Аспект поведения также гене-рирует событие move при успешном завершении операции перетаскивания. Уч-тите, что перетаскивание возможно не для всех элементов HTML. Исключениесоставляют любые теги <input>, тег <select>, тег <textarea>, кнопки и надписи.

АнимацияВ ASP.NET Atlas также входит ряд клиентских компонентов, реализующихнесложные формы анимации. Анимация делает ваши веб-приложения болееэффектными и привлекательными. Как правило, анимация применяется толькок отдельным элементам DOM и не может автоматически распространяться надочерние элементы. Например, это означает, что вы не сможете анимировать всесодержимое блочного элемента. Рассмотрим самую популярную форму ани-мации — проявление и растворение (другие типы анимации сейчас находятсяв процессе разработки; они будут доступны и полностью документированы к мо-менту выхода ASP.NET Atlas).

Для применения любого анимационного эффекта необходимо добавить в ком-понент ScriptManager ссылку на сценарий AtlasUIGIitz (соответствующий код ужеприводился в разделе, посвященном аспекту поведения Opacity, поэтому я его неповторяю).

Предположим, имеется страница с панелью ввода, на которой пользователиобязаны вводить свои учетные данные для входа на сайт. Панель остается скры-той до тех пор, пока пользователь не щелкнет на кнопке регистрации. Код такойстраницы может выглядеть примерно так:

<input type="button" id="Buttonl" value="Register" />

<div id="InputPanel" style="display:none;">

Page 211: Microsoft ASP.NET 2.0 AJAX

Элементы пользовательского интерфейса 2 1 1

<asp:TextBox ID="TextBoxl" runat="server"></asp:TextBox><br /><asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><br /><asp:Calendar runat="server" ID="Calendarl" /><asp:Button runat="server" id="Button2" text="Submit" />

</div>

Каждый элемент страниц может анимироваться (то есть отображаться с при-менением эффекта проявления):

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><button id="Buttonl" click="OnRegister" /><control id="Calendarl" /><fadeAnimation id="fader" target="Calendarl" effect="fadeln" />

</components></page>

</script>

Этот фрагмент готовит эффект анимации к работе с элементом-календаремна странице. Анимация должна запускаться явно, вызовом метода play классаBehavior. Вот что происходит при щелчке на кнопке Register:

<script type="text/javascript">function OnRegisterO{

// Отображение панели ввода$("InputPanel").style["display"] = "";

// Запуск анимацииvar fader = $object("fader");fader.pi ay();

}</script>

Аспект поведения также содержит методы stop и pause, обеспечивающие пол-ный контроль за ходом операции. Во внутренней реализации он запускает тай-мер и периодически изменяет уровень прозрачности целевого элемента.

ПРИМЕЧАНИЕКомпонент FadeAnimationBehavior может успешно применяться для создания слайдо-вых презентаций на веб-страницах, со сменой изображений по глобальному таймеру.

В данном примере мы хотим анимировать несколько элементов, но как вы-ясняется, анимация задается только для одного из них. Свойство target аспектаповедения может задаваться на программном уровне, поэтому следующий код напервый взгляд выглядит разумно:

function OnRegisterO{

// Отображение панели ввода$("InputPanel").style["display"] = "";// Получение ссылки на объект fader

Page 212: Microsoft ASP.NET 2.0 AJAX

2 1 2 Глава 5. Библиотека Microsoft AJAX

var fader = $object("fader");

// Анимация нескольких элементовfader.set_target($object("Button2"));fader.pi ay();fader.set_target($object("Calendarl"));fader.pi ay();

}

К сожалению, этот код не работает так, как ожидается. Каждый последующийвызов play останавливает текущую анимацию. Это связано с особенностямиасинхронной логики, используемой во внутренней реализации метода play. Притаком кодировании анимация не работает так, как можно было бы ожидать.

Чтобы анимировать несколько разных элементов DOM, необходимо восполь-зоваться аспектом поведения CompositeAnimation:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><control id="Calendarl" /><button id="Buttonl" click="OnRegister" /><button id="Button2" /><compositeAnirnation id="fader">

<animations><fadeAnimation target="Button2" effect="fadeln" /><fadeAnimation target="Calendarl" effect="fadeln" />

</animations></compositeAnirnation>

</components></page>

</script>

<script type="text/javascript">function OnRegisterO{

$("InputPanel").style["display"] = "";var fader = $object("fader");fader.pi ay();

}</script>

Компонент CompositeAnimation позволяет сгруппировать несколько дочерниханимаций и выполнить их как единую операцию.

ЗаключениеБиблиотека Microsoft AJAX представляет собой набор классов JavaScript, опреде-ляющих два основных программных инструмента — элементы управления и ас-пекты поведения. Впрочем, на пути к построению этих инструментов создаетсяцелый ряд фундаментальных классов, закладывающих основу для их построе-ния. Во-первых, основные классы расширяют язык JavaScript объектно-ориенти-рованными средствами (такими, как наследование, интерфейсы и пространства

Page 213: Microsoft ASP.NET 2.0 AJAX

Заключение 2 1 3

имен). Во-вторых, фундаментальные классы определяют базовое поведение ком-понентов и элементов для построения иерархии классов, напоминающей специа-лизированную версию .NET Framework. Компоненты Atlas, как и компоненты.NET Framework, представляют собой классы без пользовательского интерфейса,рассчитанные на многократное использование. В них реализован набор общихинтерфейсов и механизм обнаружения изменений свойств.

Самой распространенной разновидностью компонентов Atlas являются аспек-ты поведения клиентской стороны. С другой стороны, элементы представляютсобой многократно используемые классы, в которых возможности пользова-тельского интерфейса играют ключевую роль. Элементы Atlas — классы на базеJavaScript, работающие на стороне клиента и предоставляющие общую функцио-нальность (например, текстовые поля, кнопки и надписи).

В этой главе мы рассмотрели клиентские элементы и аспекты поведения Atlasи сравнили их с серверными расширителями элементов, описанными в главе 4.Тема привязки данных не рассматривалась; объекты данных, а также связанныес ними элементы и аспекты поведения будут описаны в главе 6.

В следующей главе мы вернемся к теме служб, кратко упомянутой в главе 2.В частности, в ней будет показано, как вызывать веб-службы из страниц Atlasи как организовать доступ к функциональности страницы при помощи служб.

Page 214: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 6 Обращение к сервернымслужбамВ этой главе:I Встроенные прикладные службыI Использование веб-службI Связь с внешними веб-службами

Главным фактором, обусловившим успех и быстрое распространение моделиAJAX, является ее возможность выполнения большинства задач приложения настороне клиента, с ограниченным обменом данными с сервером. Тем не менеенекоторый обмен данными с сервером все же необходим. Как упоминалось в гла-вах 3 и 4, приложения Atlas могут использовать асинхронный возврат данныхдля частичного обновления страниц и обновления состояния элементов посредст-вом серверных событий. Однако в некоторых ситуациях простого возврата данныхнедостаточно для завершения желаемых действий клиента — иногда для этоготребуется выполнить определенную операцию на сервере. Результаты операциидолжны быть переданы на сторону клиента для включения в текущую страницу.

Обращение по удаленному серверному URL для выполнения некоторого кодаи получения результатов — хорошо известная схема, нашедшая самую популяр-ную реализацию в модели веб-служб. Прикладная среда Atlas предоставляет рядмеханизмов для обращения к веб-службам. В наши дни термину «веб-служба»склонны придавать слишком широкое толкование. В Atlas термином «веб-служба»обозначаются веб-службы Microsoft ASP.NET (файлы .asmx), внешние веб-служ-бы, работающие на различных платформах (например, Amazon, Google и MSN),и, наконец, службы Microsoft WCF (Windows Communication Foundation) — но-вейшей программной модели для построения связных систем, которая появитсяв .NET Framework 3.0.

Несмотря на свою расширенную, улучшенную функциональность, приложенияAtlas в первую очередь являются приложениями ASP.NET и веб-приложениями.Следовательно, их работа по-прежнему зависит от традиционного сервиса при-кладного уровня — аутентификации, управления состоянием сеанса, кэширова-нием на стороне сервера, профилями пользователей, проверкой информацииролей и принадлежности к группам. Серверная среда ASP.NET предоставляетв распоряжение разработчика такие средства, как объект HttpContext (с дочернимиобъектами Session, Cache, Profile и User, статические классы для решения распро-

Page 215: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 1 5

страненных задач вроде управления профилем или аутентификации пользовате-ля, и т.д. Библиотека Microsoft AJAX инкапсулирует часть сервера прикладногоуровня во встроенных веб-службах, с возможностью вызова и управления состороны клиента. В этой главе мы рассмотрим связи между прикладной средойAtlas и миром веб-служб. Читатель узнает, как настроить приложение Atlas дляработы с прикладными службами, как пользоваться службами ASP.NET и под-ключаться к веб-службам на внешних серверах.

Встроенные прикладные службыСреды серверного программирования — такие, как ASP.NET, классическая плат-форма ASP и Java Server Pages — формируют абстрактную прослойку, предо-ставляющую сервисные функции веб-приложениям. К числу таких сервисныхфункций относится управление состоянием сеанса, аутентификация, проверкапринадлежности к группам и кэширование. Вследствие самой архитектуры этисерверные функции доступны только для серверного кода и недоступны напря-мую для JavaScript и объектной модели страницы.

В результате клиентская страница, которой потребуется обновить состояниесеанса или провести аутентификацию пользовательских данных, должна иници-ировать полный возврат данных страницы или, как минимум, обратиться с вызовомк веб-службе. Прикладные службы Atlas представляют собой обычные веб-служ-бы ASP.NET, предоставляющие доступ к сервисным функциям со стороны сер-вера, которые может быть полезно вызывать со стороны клиента.

Atlas предоставляет встроенные «обертки» для двух серверных служб: аутен-тификации форм и проверки данных пользовательского профиля.

Аутентификация формЧтобы защитить веб-страницы от посторонних пользователей, вы помещаетев начало каждой из них относительно шаблонный код и перенаправляете пользо-вателя на страницу входа. На странице входа пользователю предлагается ввестисвои регистрационные данные. Если аутентификация прошла успешно, пользо-ватель перенаправляется на исходную запрашиваемую страницу. Аутентифика-ция форм и является встроенной инфраструктурой ASP.NET, реализующей опи-санную схему для входа в систему.

Серверная аутентификация файла требует дополнительной страницы вводаи двух HTTP-команд перенаправления. Можно ли выполнить аутентификациюпрямо на стороне клиента без перенаправления? Оказывается, можно. КлассJavaScript Sys.Services._AuthenticationService позволяет передать регистрационныеданные встроенной веб-службе и получить логический признак, указывающий,успешно ли прошла аутентификация.

Использование класса JavaScript ускоряет аутентификацию пользователей,так как форма регистрации может быть встроена в существующую страницу(вместо перенаправления на специализированную страницу ввода регистраци-онных данных).

Page 216: Microsoft ASP.NET 2.0 AJAX

2 1 6 Глава 6. Обращение к серверным службам

Веб-служба аутентификацииСлужба аутентификации Atlas реализована в виде веб-службы ASP.NET. Она зако-дирована в классе AuthenticationWebService из пространства имен Microsoft.Web.Services.Standard, входящего в сборку Microsoft.Web.Atlas. Класс AuthenticationWeb-Service соответствует следующему URL:

ScriptServices/Microsoft/

Web/Services/

Standard/AuthenticationWebService.asmx

Класс JavaScript Sys.Services._AuthenticationService представляет собой «оберт-ку» для приведенного URL. Взглянув на реализацию класса JavaScript в файлеatlas.js, вы увидите следующий исходный код:

Type.registerNamespace('Sys.Services');

Sys.Services._AuthenticationService = functionO {this.path = "ScriptServices/.../AuthenticationWebService.asmx";

var cm= Sys.Net.ServiceMethod.createProxyMethod;cm(this, "login", "userName", "password", "createPersistentCookie");cm(this, "logout");cm(this, "validateUser", "userName", "password");

}Sys.Services._AuthenticationService.registerSealedClass(

'Sys.Services._AuthenticationService');Sys.Services.AuthenticationService =

new Sys.Services._AuthenticationService();

ПРИМЕЧАНИЕИмя класса JavaScript начинается с символа подчеркивания (_). Впрочем, в своих при-ложениях вы будете использовать автоматический созданный глобальный экземплярэтого класса с именем Sys.Services.AuthenticationService. Этот прием является своегорода имитацией статических методов в языке JavaScript.

Интересно заметить, что вы не найдете файлов .asmx в своей установке Atlas,в своем приложении и вообще где-либо на серверном компьютере. Как мы вскореувидим, приложения Atlas обрабатывают запросы .asmx с использованием спе-циализированных обработчиков HTTP, отличающихся от обработчиков HTTP,используемых классическими приложениями ASP.NET. Специальный обработчиквеб-службы распознает запрашиваемый URL и связывает его с типом сервера.Например, URL AuthenticationWebService.asmx отображается на тип Authentication-WebService, а URL ProfileWebService.asmx - на тип ProfileWebService.

Программный интерфейс службы аутентификацииВ табл. 6.1 перечислены методы службы аутентификации. Обратите внимание:в таблице представлены методы веб-службы на стороне сервера, то есть методыкласса AuthenticationWebService. Тем не менее «оберточный» класс JavaScript —

Page 217: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 1 7

Sys.Services._AuthenticationService — обладает тем же набором методов с одинако-выми сигнатурами.

Таблица 6.1. Веб-методы службы аутентификации

Метод Описаниеlogin Проверяет регистрационные данные и выдает аутентификационный

мандат, если данные прошли проверкуlogout Заставляет сервер прекратить действие аутентификационного мандатаvalidateUser Проверяет регистрационные данные и возвращает логический признак

Метод Atlas login обладает следующей сигнатурой:[WebMethod]public bool login(

string userName,string password,bool createPersistentCookie)

Первые два аргумента (userName и password) задают регистрационные данные;последний логический аргумент указывает, нужно ли создавать объект cookie длядолгосрочного хранения. При проверке пользователя с использованием механиз-ма аутентификации форм cookie создается и присоединяется к ответу. В даль-нейшем этот объект cookie называется «аутентификационным мандатом».

Если аргументу createPersistentCookie задано значение false, срок действиявыданного мандата истекает через 30 минут. Если выбран режим долгосрочногосоздания мандата, его срок действия истечет через 50 лет. Что делать, если по-требуется создать cookie с промежуточным сроком действия — между 30 минута-ми и 50 годами? Для этого следует задать нужный промежуток времени в мину-тах в атрибуте timeout секции <authentication> файла web.config.

Метод веб-службы login использует следующий код для выполнения своейработы:

if (Membership.Provider.ValidateUser(userName, password)){

FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);return true;

}return false;

Как видите, для проверки используется текущий провайдер принадлежности,а для создания cookie используется метод SetAuthCookie класса FormsAuthen-tication. Это означает, что при создании мандата аутентификации используетсябольшинство параметров, определенных в секции <authentication> конфигураци-онного файла.

Метод logout вызывается без аргументов и просто удаляет cookie из ответа.Во внутренней реализации он в конечном счете сводится к вызову метода SignOutкласса FormsAuthentication.

Page 218: Microsoft ASP.NET 2.0 AJAX

2 1 8 Глава 6. Обращение к серверным службам

ПРИМЕЧАНИЕСлужба аутентификации Atlas не работает с приложениями, использующими схемуаутентификации без применения cookie. Метод SetAuthCookie работает так, как обычнов классических приложениях ASP.NET, и изменяет возвращаемый URL с включениемв него аутентификационного мандата. Однако в классических приложениях ASP.NETсистемный компонент (фильтр ISAPI aspnet_filter.dll) вмешивается в обработку, пере-мещает мандат в заголовок и заменяет URL тем, который ранее запрашивался.При выполнении аутентификации через обращение к веб-службе не генерируется но-вый запрос, который мог бы быть перехвачен фильтром. В Atlas вызывающая страницапросто получает ответ о результате аутентификации — возможно, с прикрепленнымк ответу cookie. Так как замена URL не выполняется, Atlas не сможет поддерживатьаутентификацию без применения cookie.

Наконец, метод validateUser проверяет регистрационные данные, но ограничи-вается возвратом логического признака. Он не имеет ничего общего с аутенти-фикационными мандатами. Псевдокод метода выглядит так:

[WebMethocfpublic bool validateUser(string userName, string password){

// Проверить, доступна ли поддержка аутентификации AtlasAuthenticationWebServi се.CheckAuthenticationServicesEnabled();

// Проверить регистрационные данные с использованием// текущего провайдера принадлежностиreturn Membership.Provider.ValidateUser(userName, password);

}

Аутентификация Atlas может производиться только через провайдера принад-лежности. Если вам потребуется реализовать нестандартную логику аутентифи-кации пользователей, постройте специализированного провайдера.

Конфигурация службы аутентификацииСлужба аутентификации Atlas требует задания нескольких атрибутов в фай-ле web.config приложения. В частности, необходимо разрешить использованиеслужбы:

<authenticationService enabled="true" />

По умолчанию служба аутентификации отключена.Секция <authenticationService> находится в новой секции <Microsoft.Web>, от-

носящейся к Atlas. Обе секции должны быть правильно зарегистрированы.<configuration>

<configSections><sectionGroup name="inicrosoft.web"

type="Microsoft.Web.Configuration.MicrosoftWebSectionGroup"><section name="authenticationService"

type="Microsoft.Web.Configuration.AuthenticationServiceSection"requirePermission="false"/>

<section name="profileService"type="Microsoft.Web.Configuration.ProfiIeServiceSection"

Page 219: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 1 9

requirePermission="false"/></sectionGroup>

<configSections>

</configuration>

В приложениях Atlas, построенных с использованием шаблона Microsoft VisualStudio 2005, необходимые настройки уже включены в стандартный файл web.config.

Помимо настройки секций, специфических для Atlas, для использования вне-полосной аутентификации Atlas необходимо включить аутентификацию формASP.NET в секции <system.web>:

<system.wet»<authentication mode="Forms" />

</system.wet»

ПРИМЕЧАНИЕПочему для включения аутентификации в приложениях Atlas необходимы два разныхпараметра? Приложения Atlas остаются приложениями ASP.NET, хотя в них и добави-лась новая функциональность. Runtime-среда, обрабатывающая запросы, остается од-ной и той же как в классических приложениях, так и в приложениях Atlas ASP.NET.Необходимость настройки двух разных параметров объясняется тем, что в настоящеевремя Atlas реализуется в виде «надстройки», использующей некоторые функцииASP.NET. В следующей версии ASP.NET функциональность Atlas будет полностьюинтегрирована. Вероятно, когда это произойдет, параметры службы аутентифика-ции Atlas будут настраиваться непосредственно в подсекции <authentication> секции<system.web>.

Использование службы аутентификации в приложенииВ классическом приложении ASP.NET, настроенном для использования аутенти-фикации форм, защищенные страницы группируются в одной или нескольких вло-женных папках, при этом локальный файл web.config содержит следующий код:

<configuration><system.wet»

<authorization><deny users="?" /><allow users="*" />

</authorization></system.web>

</configuration>

Приведенный код блокирует анонимных пользователей (обозначаемых вопро-сительным знаком) и разрешает доступ всем остальным. Таким образом, когдапользователь переходит к любой странице в данной папке, запрос перехватыва-ется модулем аутентификации форм. Если к запросу не присоединен действитель-ный мандат, пользователь перенаправляется на страницу ввода регистрационныхданных. К ключевым особенностям этой модели следует отнести то, что аутенти-фикация выполняется в случае необходимости, а ее прохождение автоматически

Page 220: Microsoft ASP.NET 2.0 AJAX

2 2 0 Глава 6. Обращение к серверным службам

упрощается системой. Конечно, на главной странице можно разместить ссылкуна страницу ввода данных, чтобы пользователи могли пройти аутентификациюперед попыткой обращения к защищенным страницам. Впрочем, такой подходне является строго обязательным с функциональной точки зрения. Благодаря тому,что механизм аутентификации форм встроен в ASP.NET, такая модель будет ра-ботать в приложении Atlas без необходимости внесения каких-либо изменений.

Однако основной целью технологии Atlas является сокращение количестваперенаправлений и полных возвратов данных. В приложении Atlas форма вводарегистрационных данных обычно встраивается в основную страницу, а обраще-ние к службе аутентификации производится тогда, когда пользователь щелкаетна кнопке Log In. На рис. 6.1 показан пример страницы Atlas с изначально скры-той панелью ввода регистрационных данных.

Рис. 6 . 1 . Реализация аутентификации в приложениях Atlas

Как анонимные, так и проверенные пользователи могут обращаться к страни-це и пользоваться ее возможностями; другие функции доступны только для за-регистрированных пользователей.

Процесс входа/выхода из системыФорма ввода регистрационных данных обычно скрыта от пользователя. Выможете легко создать скрытую панель при помощи одного из расширителей,упоминавшихся в главе 4. Простейшая форма ввода представляет собой таблицу

Page 221: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 2 1

с парой текстовых полей и кнопкой. Излишне напоминать, что поля ввода мож-но снабдить любыми расширителями по вашему усмотрению (рис. 6.2).

Рис. 6.2. Сворачиваемая форма ввода регистрационных данных

Разумеется, в приложениях Atlas кнопка Log In является клиентской кнопкойи указывает на фрагмент кода JavaScript для вызова функций аутентификации:

<input type="button" id="LoginButton" value="Log In" onclick="OnLogin()" />

Функция On Log in выглядит примерно так:function OnLoginO{

}

Sys.Services.AuthenticationService.login(username.value, password.value, false, OnLoginComplete);return false;

Как видите, метод login класса JavaScript получает четвертый аргумент — функцию обратного вызова JavaScript. В конечном счете этот класс являетсяпосредником для вызова веб-службы; классы-посредники дополняют сигнатуруметода необязательной функцией обратного вызова, которая активизируется

Page 222: Microsoft ASP.NET 2.0 AJAX

2 2 2 Глава 6. Обращение к серверным службам

при возврате из метода. Возможная реализация OnLoginComplete может выгля-деть так:

function OnLoginComplete(result){

if (result){

// UserName и Password - идентификаторы полей ввода$("UserName").value = "";$("Password").value = "";CloseLoginPanel();

}else

alertC'Sorry, your credentials appear to be invalid.");}

function CloseLoginPanel(){

var behavior = $object("CollapseLoginPanell");behavior.set_Collapsed(true);

}

Возвращаемое значение метода веб-службы передается функции обратноговызова. В нашем примере это логический флаг, обозначающий результат аутен-тификации. Если проверка прошла успешно, мы сбрасываем пользовательскийинтерфейс формы ввода регистрационных данных и сворачиваем панель.

<asp:Panel id="LoginPanel" runat="server" Height="0">

</asp:Panel><act:Col 1apsi Ы ePanelExtender runat="server">

<act:Col 1apsi Ы ePanelPropertiesID="CollapseLoginPanel1"TargetControlID="LoginPanel"

/>

</act:Col 1apsi Ы ePanelExtender>

На рис. 6.3 показано, как выглядит ответ HTTP для запроса, обращенногок URL AuthenticationWebService.asmx для выполнения метода login (в окне утилитыWeb Development Helper, кратко упоминавшейся в главе 2). Как видите, ответHTTP содержит дополнительный объект cookie с именем .ASPXAUTH. Это и естьаутентификационный мандат, выданный сервером и переданный клиенту. Начи-ная с этого момента пользователь может обращаться ко всем защищенным стра-ницам приложения, вплоть до истечения срока действия мандата.

Чтобы дать пользователю возможность выйти из системы «по рецепту Atlas»,мы добавляем еще одну клиентскую кнопку и связываем ее со следующим кодомJavaScript:

function Logout(){

Sys.Services.AuthenticationService. 1 ogout(OnLogoutComplete);return false;

}

При возврате из функции ответ HTTP выглядит так, как показано на рис. 6.4.

Page 223: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 2 3

Рис. 6.3. Ответ HTTP для вызова метода login службы аутентификации

Рис. 6.4. Ответ HTTP для вызова метода logout службы аутентификации

Page 224: Microsoft ASP.NET 2.0 AJAX

2 2 4 Глава 6. Обращение к серверным службам

Тело cookie .ASPXAUTH стало пустым, и мандат уже не может использовать-ся для получения доступа к защищенным страницам приложения.

Типичные усовершенствованияпользовательского интерфейсаЛюбые приложения, использующие сервис аутентификации, должны предостав-лять дополнительные элементы пользовательского интерфейса для вывода при-ветствия зарегистрированному пользователю и для выхода из системы. Крометого, на некоторых страницах также могут размещаться условные элементы, ото-бражаемые только для аутентифицированных запросов.

Как узнать, прошел ли текущий запрос аутентификацию?В классической модели ASP.NET достаточно проверить свойство Request.

IsAuthenticated в Page_Load (или там, где вам понадобится эта информация).В Atlas дело обстоит несколько иначе.

При возврате управления методом login вы знаете, был ли аутентифицировантекущий пользователь. Предположим, пользователь перешел к другой страницеприложения, а затем щелкнул на кнопке Back или любой ссылке, возвращающейк исходной странице. При возврате к исходной странице браузер пользователятеряет всю информацию о состоянии аутентификации — в конце концов, состояниеаутентификации было всего лишь значением глобальной переменной JavaScript.Если не учесть эту возможность при проектировании приложения, пользователь-ский интерфейс может указывать на то, что пользователь не вошел в систему,тогда как модуль аутентификации будет правильно обрабатывать дальнейшиезапросы к защищенным страницам. Рассмотрим блок кода пользовательского ин-терфейса для вывода имени зарегистрированного пользователя:

<div runat="server" id="LoggedIn" style="display:none;"><h2>Hey,&nbsp;<asp:Label id="Loggedllser" runat="server" />&nbsp;&nbsp;<input type="button" value="Log out" onclick="Logout()" /></h2>

</div><div runat="server" id="NotLoggedIn" style="display:none;color:red;">

<h2>Not logged in</h2></div>

Первый блок <div> используется для зарегистрированных пользователей, а вто-рой — для всех остальных. Переключение осуществляется на основании резуль-тата вызова login и состояния аутентификации запроса. Чтобы упростить задачу,включите следующий фрагмент в событие Page_Load кодового файла:

protected void Page_Load(object sender, EventArgs e){

if (Request.IsAuthenticated){

LoggedIn.Style["display"] = "";NotLoggedIn.Style["display"] = "none";_oggedUser.Text = User.Identity.Name;// Отобразить элементы пользовательского интерфейса// для зарегистрированных пользователей

}

Page 225: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 2 5

else{

_oggedIn.Style["display"] = "none";NotLoggedIn.Style["display"] = "";_oggedUser.Text = "";// Скрыть элементы пользовательского интерфейса// для зарегистрированных пользователей

}}

Этот код гарантирует инициализацию элементов пользовательского интерфей-са при первой загрузке страницы и при всех последующих обновлениях (по ссылкеили кнопкам Back/Forward). Кроме того, мы расширяем функции OnLoginCompleteи OnLogoutComplete для динамического обновления пользовательского интер-фейса при входе или выходе пользователя прямо со страницы. Например, можновоспользоваться следующей функцией:

<script type="text/javascript">var currentUser = $("LoggedUser");var username = $("UserName");var password = $("Password");var loggedln = $("LoggedIn");var notLoggedln = $("NotLoggedIn");

function HandleLoginLogoutState(userLogged){

if (userLogged){

notLoggedln.style.display = "none";loggedln.style.display = "";currentUser.innerText = username.value;// Отобразить элементы пользовательского интерфейса// для зарегистрированных пользователей

}else{

loggedln.style.display = "none";notLoggedln.style.display = "";currentUser.innerText = "";// Скрыть элементы пользовательского интерфейса// для зарегистрированных пользователей

}}</script>

Функция HandleLoginLogoutState вызывается как из OnLoginComplete, так и изOnLogoutComplete; при этом ей передаются значения true и false соответственно.

ПрофилиЧтобы ваши страницы ASP.NET стали более удобными, более функциональны-ми и приятными в использовании, в веб-приложение можно включить механизмперсонализации, который позволяет пользователям сохранять и загружать свои

Page 226: Microsoft ASP.NET 2.0 AJAX

2 2 6 Глава 6. Обращение к серверным службам

личные настройки. Возможности персонализации в ASP.NET 2.0 строятся на ос-нове концепции пользовательского профиля.

Пользовательский профиль представляет собой совокупность свойств, кото-рые объединяются runtime-средой ASP.NET 2.0 в динамически сгенерированныйкласс. Приложение определяет собственную модель данных в конфигурацион-ном файле, а runtime-среда ASP.NET делает все остальное, разбирая и компили-руя эту модель в класс.

Каждое поле класса соответствует фрагменту информации, специфическомудля текущего пользователя. Все данные профилей сохраняются для конкретногопользователя и существуют до тех пор, пока не будут удалены обладателем ад-министративных привилегий.

При запуске приложения и отображении страницы ASP.NET динамически со-здает объект профиля, который содержит свойства, определенные в модели дан-ных (с правильными типами). Созданный объект добавляется в текущий объектHttpContext и становится доступным для страниц через свойство Profile. Профиль-ный сервис ASP.NET реализуется через модуль HTTP. Модуль вступает в делопосле аутентификации запроса и загружает данные для конкретного пользователя.(Для анонимных пользователей генерируется уникальный идентификатор, со-храняемый в cookie .ASPXANONYMOUS.) В конце обработки запроса объект про-филя сохраняется в хранилище данных, готовый к следующему использованию.

Чтение и запись профильных свойств в серверных страницах осуществляетсячерез объект HttpContext.Profile. Можно ли сделать то же в странице Atlas привнеполосном возврате данных? Оказывается, можно. Класс Sys._Profile из файлаatlas.js выполняет функции «моста» между клиентской страницей и сервернымобъектом HttpContext.Profile.

ПРИМЕЧАНИЕХранилище данных для профильной службы настраивается в файлеweb.config с исполь-зованием специальных компонентов, называемых провайдерами профилей (profileproviders).

Веб-служба профилейПрофильный сервис Atlas реализован в виде веб-службы ASP.NET. Она закоди-рована в классе ProfileWebService из пространства имен Microsoft.Web.Services.Standard, входящего в сборку Microsoft.Web.Atlas. Класс ProfileWebService соответ-ствует следующему URL:

ScriptServices/Microsoft/

Web/Services/

Standard/Profi1eWebService.asmx

Класс JavaScript Sys._Profile представляет собой «обертку» для приведенногоURL. Класс предоставляет расширенный программный интерфейс со свойства-

Page 227: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 2 7

ми и событиями, но центральное место в нем занимают два метода load и save,отображаемые на веб-методы серверного класса веб-службы ProfileWebService.

В своих страницах Atlas вам не придется явно создавать экземпляры классаSys._Profile; вместо этого вы будете использовать объект Sys.Profile, который пред-ставляет собой глобальную ссылку на единый экземпляр профильной службы:

Sys.Profile = new Sys._Profile();

Кстати говоря, в файле atlas.js этот код следует непосредственно за объявле-нием класса Sys._Profile.

Программный интерфейс службы профилейВ табл. 6.2 перечислены методы серверной веб-службы профилей. Как упоми-налось ранее, класс называется ProfileWebService и находится в сборке Microsoft.Web.Atlas.

Таблица 6.2. Веб-методы службы профилей

Метод ОписаниеGetProfile Получает коллекцию имен свойств и возвращает хеш-таблицу,

заполненную парами «имя/значение»SetProfile Получает хеш-таблицу, заполненную парами «имя/значение»,

и сериализует ее содержимое в хранилище данных профиля

Точная сигнатура метода GetProfile приведена в следующем фрагменте:[WebMethocTpublic IDictionary GetProfi1e(string[] properties)

Аргумент properties содержит список профильных свойств, загружаемых в объ-ект JavaScript Sys.Profile. Если аргумент равен null, загружаются все свойствапрофиля. Метод GetProfile возвращает хеш-таблицу с одной записью для каждогозапрашиваемого свойства. Запись состоит из имени и значения.

Метод SetProfile обладает следующей сигнатурой:[WebMethocTpublic void SetProfileGDictionary values)

Он получает хеш-таблицу и обновляет свойства в хранилище данных задан-ными значениями.

В отличие от службы аутентификации, программный интерфейс службы про-филей JavaScript шире интерфейса соответствующей веб-службы. В этом нетруд-но убедиться по табл. 6.3.

Поскольку загрузка и сохранение выполняются в асинхронном режиме, выдолжны добавить обработчики для событий loaded и saved для выполнения опе-раций, требующих логически целостного состояния профильной службы.

Автосохранение — функция системы профилей, которая на классическойплатформе ASP.NET включалась по умолчанию. В системе профилей Atlas этафункция отключена; это означает, что команды, связанные с сохранением дан-ных, должны отдаваться явно.

Page 228: Microsoft ASP.NET 2.0 AJAX

2 2 8 Глава 6. Обращение к серверным службам

Таблица 6.3. Члены класса Sys._Profile

Член класса ОписаниеautoSave Логическое свойство, показывающее, должна ли служба периодически

и автоматически сохранять объект профиля на сервере. По умолчаниюзадается равным false

isDirty Логическое свойство, показывающее, содержит ли текущий объектпрофиля незакрепленные изменения, которые еще не были сохраненына сервере

properties Массив свойств, предоставляющий доступ к отдельным свойствамобъекта профиля

Load Метод, вызываемый для заполнения свойства properties даннымипрофиля. Загрузка профиля производится асинхронно

loaded Событие, происходящее непосредственно после загрузки профиляsave Метод, вызываемый для сохранения текущего состояния объекта

профиля на сервере. Если свойство autoSave истинно, метод вызываетсяавтоматически. Сохранение профиля производится асинхронно

saved Событие, происходящее непосредственно после сохранения профиля

Поскольку служба Atlas работает на базе подсистемы профилей ASP.NET, выможете ограничиться частью прикладной модели данных, закодированной в фай-ле web.config. Обычно такой подход удобен тем, что он позволяет передаватьтолько те профильные данные, к которым необходим доступ со стороны клиента.

Конфигурация службы профилейЧтобы использовать службу профилей Atlas, вам придется немного потрудитьсянад ее конфигурацией. В частности, необходимо явно разрешить использованиеслужбы в подсекции <profileService> новой секции <Microsoft.Web>:

<profileService enabled="true"setProperties="свойство1;свойство2; ..."getProperties="cBOHCTBol;cBOHCTBo2; ..." />

Чтобы разрешить чтение и изменение свойств профиля из приложений Atlas,перечислите их имена в атрибутах setProperties и getProperties. Атрибут get-Properties содержит список имен читаемых свойств, разделенных символом «;»(точка с запятой). В атрибуте setProperties перечислены имена записываемыхсвойств, которые также разделяются символом «;». Чтобы сделать доступнымивсе свойства, воспользуйтесь условным обозначением «*» или перечислите всесвойства по именам.

Модель данных, заложенная в основу службы профилей, определяется в под-секции <profile> секции <system.web>. Вот как выглядит модель данных, котораябудет использована в следующем примере:

<profile><properties>

<group name="UI">

Page 229: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 2 9

<add name="BackColor" type="string" /></group>

<add name="LastPane" type="integer" /></properties>

</profile>

Соответственно, секция <profileService> принимает следующий вид:<profileService enabled="true"

setProperties="LastPane;UI.BackColor"getProperties="LastPane;UI.BackColor" />

Как упоминалось ранее, атрибуты setProperties и getProperties могут содержатьподмножество свойств, определенных в модели данных. Два набора свойств необязаны совпадать; это означает, что для некоторого свойства профиля можетбыть разрешено чтение из страниц Atlas, но не запись (или наоборот). Если вашамодель данных включает группы, при указании свойства в секции <profileService>можно воспользоваться схемой группа.свойство.

Использование службы профилей в приложенииСлужба профилей тесно связана со службой аутентификации, так как объект про-филя содержит информацию, относящуюся к конкретному аутентифицирован-ному пользователю. Анонимным пользователям разрешается иметь собственныепрофили — при условии, что для анонимных пользователей такая возможностьбудет включена в конфигурационном файле. Для анонимного пользователягенерируется код Guid, однозначно идентифицирующий его; когда анонимныйпользователь зарегистрируется, данные переносятся из анонимного профиляв зарегистрированный. В следующем примере рассматриваются только зарегист-рированные пользователи.

Приложения с поддержкой профилей должны реализовать ряд функциональ-ных аспектов.I В страницах, использующих данные из профилей, обработчик Page_Load дол-жен содержать серверный код, обеспечивающий правильную настройку до-черних элементов в случае возврата данных или перенаправления.

I Приложение должно содержать одну или несколько страниц, на которых за-регистрированные пользователи могут отредактировать свой профиль. Вне-сенные изменения сохраняются в хранилище данных профилей.

I На страницах должны находиться кнопки Login/Logout, позволяющие пользо-вателям входить и выходить из системы по своему усмотрению.

I При использовании Atlas пользовательский интерфейс страниц с поддержкойпрофилей должен обновляться сценарным кодом, чтобы в нем отражалсявход новых пользователей или изменения в объектах профилей.На рис. 6.5 показан пример страницы, использующей службу аутентифика-

ции для входа пользователей, и службу профилей для чтения и обновления лич-ных данных.

Page 230: Microsoft ASP.NET 2.0 AJAX

2 3 0 Глава 6. Обращение к серверным службам

Рис. 6.5. Пример страницы, использующей службу профилей

После подключения пользователя элемент Accordion (см. главу 4) использует-ся для вывода информации. Элемент состоит из четырех панелей, которые поль-зователь может открывать по своему усмотрению. Индекс панели, выбранной привыходе со страницы, сохраняется в профиле, чтобы при возвращении пользова-теля к странице на ней была открыта та же панель (рис. 6.6).

Дочерние элементы скрываются и отображаются в зависимости от состоянияаутентификации запроса. Если пользователь прошел проверку, код Page_Loadприменяет данные из профиля. В нашем примере задача сводится к простомувыбору панели элемента Accordion и настройке фона страницы:

protected void Page_Load(object sender, EventArgs e){

if (Request.IsAuthenticated){

// Настройка элементов для зарегистрированного пользователя_oggedIn.Style["display"] = "";NotLoggedIn.Style["display"] = "none";_oggedUser.Text = User.Identity.Name;_oginBlock.Style["display"] = "none";AccordionPanel.Style["display"] = "";

ApplyProfileO;}else{

// Настройка элементов для анонимного пользователя_oggedIn.Style["display"] = "none";NotLoggedIn.Style["display"] = "";

Page 231: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 3 1

LoggedUser.Text = "";

LoginBlock.Style["display"] = "";

AccordionPanel.Style["display"] = "none";

protected void ApplyProfile()

{

// Выбор цвета фона страницы

string bgColor = Profile.UI.BackColor;

if (!String.IsNullOrEmpty(bgColor))

Body.Style["background-color"] = bgColor;

// Выбор последней активной панели

Accordion1.SelectedIndex = Profile.LastPane;

Рис. 6.6. Персонализированная страница после входа пользователя

Page 232: Microsoft ASP.NET 2.0 AJAX

2 3 2 Глава 6. Обращение к серверным службам

Приведенный фрагмент содержит чистый, классический код ASP.NET. Он га-рантирует правильную работу страницы при вызове из адресной строки, припереходе по гиперссылке или переходе пользователя в прямом или обратном на-правлении от текущей страницы. Та же логика должна быть выражена сценар-ным кодом при регистрации пользователя с использованием службы аутентифи-кации Atlas или редактировании профиля через службу профилей. Следующийсценарий активизируется после входа пользователя и загрузки данных профиля:

function OnLoginO{

Sys.Services.AuthenticationService.1ogin(username.value, password.value, false, OnLoginComplete);

return false;}function OnLoginComplete(result) {

HandleLoginLogoutState(result);if (result){

CloseLoginPanel();_oadProfile();

}else

alertC'Sorry, your credentials appear to be invalid. Try again.");}

function LoadProfileO{

Sys.Profile.load();}

Учтите, что метод load работает асинхронно. Для выполнения кода, использую-щего информацию из профиля, потребуется обработчик события loaded. Луч-шим местом для регистрации обработчика события является код инициализациистраницы Atlas:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components>application load="PageInit()" unload="PageEnd()"></application>

</components></page>

</script>

<script type="text/javascript">function PagelnitO{

Sys.Profi1e.1oaded.add(0nProfi1eLoaded);Sys.Profi1e.saved.add(0nProfi 1 eSaved);

}function PageEndO{

Sys.Profi1e.1oaded.remove(OnProfi 1 eLoaded);Sys.Profi1e.saved.remove(OnProfi 1 eSaved);

}

Page 233: Microsoft ASP.NET 2.0 AJAX

Встроенные прикладные службы 2 3 3

function OnProfileLoadedO{

var panelndex = Sys.Profile.properties.LastPane;var bgColor = Sys.Profile.properties["UI.BackColor"];var accordionBehavior = $object("Accordionl_AccordionProperties");accordionBehavior.set_Selectedlndex(panelndex);$("Body").style.backgroundColor = bgColor;

}</script>

Функция OnProfileLoaded задает фоновый цвет страницы и выбирает послед-нюю выбранную панель в элементе Accordion. Предполагается, что тело страни-цы имеет пометку runat="server" и снабжено идентификатором Body. Имя иден-тификатора выбирается произвольно. Тег <body> должен быть серверным тегом,чтобы фоновый цвет страницы можно было выбирать на программном уровне изстраницы ASP.NET. Если бы вы хотели только иметь возможность читать и за-давать цвет фона из сценария, такой тег не был бы обязательным — хватило быодного идентификатора. Тем не менее, как упоминалось ранее, страницы с под-держкой профилей также должны содержать серверную версию любого клиент-ского кода, работающего с профильными данными.

Во внутренней реализации серверного элемента Accordion используется рас-ширитель, генерирующий сценарный аспект поведения. Помимо предоставленияклиентского поведения, этот аспект дополняет компонент Accordion клиентскойобъектной моделью. В главе 5 читатель узнал, как создавать ссылки на компо-ненты Atlas, но элемент Accordion прежде всего является серверным элементом.Как получить ссылку на клиентский аспект поведения Accordion? Воспользуй-тесь условной записью XXX_AccordionProperties, где XXX — идентификатор сер-верного элемента.

// Получение клиентской объектной модели для элемента Accordiorvar accordionBehavior = $object("Accordionl_AccordionProperties");accordionBehavior.set_Selectedlndex(panelndex);

Аспект поведения Accordion обладает теми же свойствами, что и элемент Acc-ordion; например, свойство Selectedlndex позволяет получить или задать актив-ную панель.

Наш пример приложения завершается страницей, на которой каждый пользо-ватель может выбрать цвет фона страницы. Для этой цели используется класси-ческая серверная страница ASP.NET, которая читает и записывает данные про-филей при помощи серверного объекта Profile.

Когда пользователь щелкает на кнопке Save Page State (см. рис. 6.6), страницасохраняет профиль:

function SaveProfileO{

// Сохранение панели, выбранной в настоящий моментvar accordionBehavior = $object("Accordionl_AccordionProperties");Sys.Profile.properties.LastPane = accordionBehavior.get_SelectedIndex();Sys.Profile.saveO;

}

Page 234: Microsoft ASP.NET 2.0 AJAX

2 3 4 Глава 6. Обращение к серверным службам

Кроме того, метод save работает асинхронно, а после завершения операциипроисходит событие saved.

Служба Profile использует встроенную веб-службу Atlas для чтения и записипрофильных свойств на сервере. Она представляет собой клиентскую «обертку»для серверного объекта Profile, который, в свою очередь, использует провайдерапрофилей для хранения данных, относящихся к конкретному пользователю. Сер-верные страницы и страницы Atlas могут использоваться в одном приложении,работающем с данными профилей. Не полагайтесь только на Atlas; позаботьтесьо том, чтобы ваши страницы Atlas имели обработчик события Page_Load, приме-няющий данные профиля при каждой загрузке страницы.

Использование веб-службСлужбы аутентификации и профилей — две встроенные веб-службы ASP.NET,для которых библиотека Microsoft AJAX предоставляет «обертки» JavaScript.В общем случае может возникнуть необходимость вызова веб-служб по Ин-тернету. Архитектура доступа к веб-службам из Atlas делится на три уровня:I Веб-службы, принадлежащие тому же приложению, что и вызывающая стра-ница.

I Веб-службы, принадлежащие веб-приложению с поддержкой Atlas на одномсервере с вызывающим приложением, или на внешнем компьютере.

I Любые другие веб-службы, для которых возможна загрузка описания WSDL(Web Services Description Language), независимо от платформы и реализации.В первом случае вам необходимо только связать файл .asmx с элементом

ScriptManager. Во втором случае следует настроить файл web.config и включитьподдержку междоменных вызовов веб-служб Atlas. В третьем случае необходимосоздать мостовой класс для отображения внешней веб-службы на класс-посред-ника JavaScript. Во всех случаях доступ к веб-службам должен быть явно разре-шен в файле web.config.

Работа с домашними веб-службамиВеб-службы являются простейшим механизмом публикации серверного кода,который должен вызываться в ответ на действие клиента (например, щелчокна кнопке). В этом случае веб-методы службы соответствуют фрагментам кода,специфическим для данного приложения. Иначе говоря, веб-служба являетсячастью приложения, находится на том же компьютере и в том же домене, чтои приложение.

ПРИМЕЧАНИЕСуществует два способа публикации серверного кода, вызываемого со стороны клиен-та: веб-службы на домашнем сервере и методы страниц. Методы страниц преобразуютстраницу в домашнюю веб-службу и являются еще более простым способом публика-ции серверного кода. Мы уже встречались с методами страниц в главе 2 и еще вернемсяк ним позднее в этой главе.

Page 235: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 3 5

Разрешение вызова веб-службЧтобы разрешить вызовы веб-служб из приложений Atlas, необходимо добавитьследующий фрагмент в файл web.config приложения:

<microsoft.web><webServices enableBrowserAccess="true" />

</microsoft.web>

По умолчанию операции с веб-службами в Atlas запрещены. Помимо разре-шения доступа к веб-службам, также необходимо зарегистрировать специальныйобработчик HTTP для запросов .asmx:

<httpHandlers><remove verb="*" path="*.asmx"/><add verb="*" path="*.asmx"

type="Microsoft.Web.Services.ScriptHandlerFactory" />

</httpHandlers>

Обе настройки автоматически включаются в стандартный файл web.config,генерируемый шаблоном Atlas в Visual Studio 2005.

Параметр ScriptHandlerFactory определяет обработчик HTTP, которому пору-чается обработка заданного набора запросов. Запросы .asmx отличают вызовывеб-служб Atlas от обычных вызовов веб-служб из других приложений, включаяASP.NET, Microsoft Windows и браузеры. Вызовы веб-служб Atlas обслужива-ются другим обработчиком HTTP. Конечно, такие запросы обрабатываютсятолько в том случае, если доступ к веб-службам был разрешен (позднее мы вер-немся к обработчику HTTP для веб-служб Atlas).

Связывание страниц с веб-службамиДля обработки вызова веб-службы Atlas необходим класс-посредник JavaScript.Как получить такой класс? Обработчик веб-служб Atlas делает это каждый раз,когда обнаруживает URL, завершающийся суффиксом /js. Предположим, у васимеется веб-служба, находящаяся по следующему адресу:

http://localhost/IntroAtlas/WebServices/MyDataServi се.asmx

В данном примере используется веб-служба MyDataService, кратко упоминав-шаяся в главе 2. Попробуйте ввести URL в адресной строке браузера и добавитьк нему суффикс /js:

http://localhost/IntroAtlas/WebServices/MyDataService.asmx/js

Вот что вы должны получить:Type.registerNamespace('IntroAtlas.WebServices');IntroAtlas.WebServices.MyDataService = new functionO{

this.appPath = "http://localhost/IntroAtlas/";var cm = Sys.Net.ServiceMethod.createProxyMethod;cm(this, "LookupCustomer", "id");cm(this, "LookupAllCustomers");

}

Page 236: Microsoft ASP.NET 2.0 AJAX

2 3 6 Глава 6. Обращение к серверным службам

IntroAtlas.WebServices — пространство имен класса веб-службы, а LookupCustomerи LookupAIICustomers — веб-методы, определенные в классе. Полученный выводпредставляет собой класс JavaScript, имя которого соответствует классу веб-служ-бы, а прототип соответствует веб-методам службы. Приведенный выше класс Java-Script — всего лишь класс-посредник, необходимый для работы со службойMyDataService.asmx из приложения Atlas. Как видите, Atlas автоматически получаетметаданные веб-службы и генерирует класс-посредник JavaScript, упрощающий вы-зов веб-методов без прямой работы с SOAP (Simple Object Access Protocol) и WSDL.

Следующим шагом должно стать связывание класса-посредника со страницейAtlas. Эта операция может выполняться двумя способами, которые я условно назо-ву «ручным» и «автоматическим». В ручном варианте вы берете код JavaScript,полученный в результате встроенного генерирования класса-посредника в Atlas,и сохраняете его в локальном классе .js. Далее остается отредактировать файл повашему усмотрению и включить ссылку на него в страницу. Такой подход по-зволяет достаточно легко генерировать посредников JavaScript, которые затемредактируются и настраиваются вручную. По сути он мало чем отличается отпредварительного построения посредников SOAP утилитой wsdl.exe, обычно ис-пользуемого в классических приложениях ASP.NET и Windows.

Автоматический способ основан на регистрации URL веб-службы в элемен-те ScriptManager при помощи элемента <asp:ServiceReference>. Кроме того, веб-службы должны пройти программную регистрацию в событии Page_Load классакодового файла:

ServiceReference service = new ServiceReferenceO;service.Path = "-/WebServices/MyDataService.asmx";service.GenerateProxy = true;scriptManagerl.Services.Add(service);

Какой бы путь вы ни выбрали, для вызова веб-службы создается обращениек классу-посреднику через код JavaScript. Имя класса-посредника совпадает с име-нем веб-службы, и он обладает тем же набором методов.

Вызов методов веб-службОперация вызова веб-службы выполняется страницей в ответ на действие поль-зователя — например, щелчок на кнопке. Желательно, чтобы эта кнопка былаклиентской кнопкой, связанной с функцией JavaScript, как в следующем примере:

<input type="button" value="Customer details" onclick="findCustomer()" />

Она также может быть классической кнопкой отправки данных — при усло-вии, что свойство OnClickClient связано с кодом JavaScript, возвращающим falseдля предотвращения стандартного действия отправки данных:

<asp:Button ID="Buttonl" runat="server" Text="Button"OnClientClick="findCustomer();return false;" />

Функция findCustomer читает идентификатор текущего клиента из раскрываю-щегося списка и вызывает метод LookupCustomer для импортированного класса-посредника, как показано в следующем фрагменте:

<script 1anguage="javascript" type="text/javascript">function findCustomer()

Page 237: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 3 7

var list = $("CustomerList");var customerID = list.options[list.selectedIndex].value;IntroAtlas.WebServices.MyDataService.LookupCustomer(customerID, findCustomerComplete);

function findCustomerComplete(results){

$("CustomerData").style.visibility = "visible";$("companyID").innerText = results.ID;$("companyName").innerText = results.CompanyName;$("companyContact").innerText = results.ContactName;$("companyCity").innerText = results.City;

$("companyCountry").innerText = results.Country;}

</script>

Метод посредника выполняется асинхронно, но вы можете задать функциюобратного вызова, получающую управление сразу же после возврата из метода.Функция обратного вызова получает единственный параметр — возвращаемоезначение метода. Им может быть как примитивный тип (строка, число или дата),так и более сложный объект JavaScript. Последствия вызова показаны на рис. 6.7.

Рис. 6.7. Использование веб-службы для получения информации о клиенте

Page 238: Microsoft ASP.NET 2.0 AJAX

2 3 8 Глава 6. Обращение к серверным службам

Каждый метод класса-посредника JavaScript представляет собой объект классаServiceMethod, определенного в файле atlas.js. Класс ServiceMethod, в свою оче-редь, является производным от WebMethod. Все классы принадлежат простран-ству имен Sys.Services.

Кроме обычного набора параметров, поддерживаемого парным методом веб-службы, каждый веб-метод JavaScript поддерживает ряд конфигурационных па-раметров. Все эти параметры перечислены в табл. 6.4.

Таблица 6.4. Параметры конфигурации методов-посредников

Параметр ОписаниеonMethodComplete

onMethodTimeout

onMethodError

onMethodAborted

userContext

timeoutInterval

priority

useGetMethod

Определяет функцию обратного вызова JavaScript, вызываемуюпри успешном возврате из метода веб-службы

Определяет функцию обратного вызова JavaScript, вызываемуюпри возврате из метода веб-службы по тайм-ауту

Определяет функцию обратного вызова JavaScript, вызываемуюпри возникновении исключения при вызове метода веб-службы

Определяет функцию обратного вызова JavaScript, вызываемуюпри отмене вызова метода

Любое значение (строка, число, массив, словарь или объект),которое представляет контекстную информацию, передаваемуюфункциям обратного вызова

Интервал тайм-аута для вызова в миллисекундах

Числовой приоритет вызова. Допустимые значения: 0 (высокий),1 (нормальный) и 2 (низкий). Приоритеты обычно используютсяпри пакетном объединении вызовов (об этом чуть позже)

Логический признак, указывающий, следует ли использоватьоперацию GET при выполнении вызова. По умолчаниюиспользуется операция POST

При вызове любого метода-посредника можно задать любые из перечислен-ных параметров — в порядке их следования в таблице. Если требуется задатьлишь некоторые параметры, можно воспользоваться следующим синтаксисом:

function findCustomer(){

var list = $("CustomerList");var customerID = list.options[list.selectedIndex].value;

IntroAtlas.WebServices.MyDataService.LookupCustomer(customerID, // Аргумент метода{

onMethodComplete: findCustomerComplete,onMethodTimeout: findCustomerTimeout,onMethodError: findCustomerError,onMethodAborted: findCustomerAborted,timeoutInterval: 5000

);

Page 239: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 3 9

Вместо явного перечисления параметры конфигурации объединяются в мас-сив, передаваемый в дополнительном аргументе вызова метода.

Обработка результатов вызоваМетоды веб-служб ни в коей мере не ограничиваются примитивными типами — такими, как строки и целые числа. При передаче и возврате параметров веб-службдопускается использование большинства типов .NET. Такие типы .NET автома-тически сериализуются в классы JavaScript (и десериализуются) с использова-нием формата JSON (JavaScript Object Notation), в полной мере поддерживаемо-го в Atlas (см. главу 2).

В двух словах, клиентская инфраструктура Atlas JSON сериализует объектJavaScript в специальный формат, предназначенный для обмена данными, и пе-редает его по каналу связи получателю, находящемуся на стороне сервера. По-лучатель разбирает поток данных и строит соответствующий объект .NET. Ана-логичным образом серверная инфраструктура Atlas JSON берет объект .NETи сериализует его в формат обмена данными JSON. На стороне клиента по пото-ку данных создается объект JavaScript.

Этот чрезвычайно мощный механизм практически полностью прозрачен дляразработчиков Atlas. От вас потребуется лишь позаботиться о том, чтобы Atlasуспешно преобразовал ваши типы. Стандартная инфраструктура Atlas нормаль-но справляется с большинством пользовательских и системных классов. Atlasтакже регистрирует конвертеры JSON для популярных типов ADO.NET. Рассмот-рим следующий метод веб-службы MyDataService.asmx:

[WebMethocTpublic CustomerCollection LookupAllCustomers(){

return CustomerManager.LoadAl 1 0 ;}

Метод возвращает пользовательский класс-коллекцию, содержащий экземп-ляры класса Customer:

public class CustomerCollection : Collection<Customer>{

}

Как работать с этой коллекцией в функции JavaScript? Следующая функцияfindContacts присоединяется к событию onclick кнопки:

function findContacts(){

IntroAtlas.WebServices.MyDataService.LookupAl1 Customers(findContactsComplete);

}

function findContactsComplete(results){

// Получение объекта builder для построения отображаемой строкиvar builder = new Sys.StringBuilder("<br><br>");

Page 240: Microsoft ASP.NET 2.0 AJAX

2 4 0 Глава 6. Обращение к серверным службам

// Перебор коллекции с построением отображаемой строкиfor(i=0; i<results.length; i++){

// result[i] - экземпляр класса JavaScript с именем Customer.// Класс Customer обладает теми же свойствами,// что и исходный тип .NET.builder.append(results[i].ContactName);builder.append("<hr>");

}// Присоединение строки к надписи на странице$("Label1").innerHTML = builder.toStringO ;

}

Аргумент results представляет любой объект, возвращаемый методом. Если ме-тод возвращает массив или коллекцию, то results представляет массив или кол-лекцию. В нашем примере элементами коллекции являются экземпляры классаCustomer. Объект JavaScript Customer обладает такой же сигнатурой, как и ис-ходный тип .NET. На рис. 6.8 показан результат выполнения приведенного кода.

Рис. 6.8. Использование веб-службы для получения массива клиентов

Сценарный код, сгенерированный для веб-службы, включает определениеCustomer. Класс CustomerCollection представляет собой массив JavaScript, и по-средники для него не нужны.

Если вызываемому методу должен передаваться пользовательский объект, отвас потребуется лишь создать экземпляр соответствующего посредника JavaScript.Предположим, имеется метод следующего вида:

Page 241: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 4 1

[WebMethod]public Customer UpdateCustomer(Customer cust){

}

На странице находится раскрывающийся список, в котором выбирается имяклиента. Кроме того, на ней размещено текстовое поле, в котором пользовательможет ввести имя нового клиента. Следующий сценарий показывает, как реали-зуется создание новой записи:

function updateCustomer(){

var textbox = $("ContactName");var contactName = textbox.value;var list = $("CustomerList");var customerID = list.options[list.selectedIndex].value;

var c = new IntroAtlas.Customer();c.ID = customerID;c.ContactName = contactName;// Здесь могут задаваться другие свойства

// Обновление информации о клиентеIntroAtlas.WebServices.MyDataService.UpdateCustomer(

c, updateCustomerComplete);}function updateCustomerComplete(results){

// Аргумент results представляет возвращаемое значение метода

}

В конечном счете, при вызове методов веб-служб у вас найдутся более важ-ные заботы, чем тип данных. Базовая инфраструктура JSON берет на себя боль-шую часть проблем. При использовании сложных типов данных — таких, какDataTable и других типов ADO.NET — может потребоваться специализирован-ный конвертер JSON. Atlas предоставляет такие конвертеры для многих распро-страненных типов.

ПРИМЕЧАНИЕКонвертер JSON представляет собой класс, производный от JavaScriptConverter — ба-зового класса, определяемого в пространстве имен Microsoft.Web.Script.Serializationосновной сборки Atlas. Конвертер обычно переопределяет несколько методов для вы-полнения сериализации в поток данных JSON и десериализации по формату JSON.

Перехват исключений и тайм-аут при вызове методовЧто если при вызове метода веб-службы произойдет ошибка с выдачей исклю-чения? Можно ли ограничить выполнение метода по времени и отменить его,если метод занимает слишком много времени? В табл. 6.4 были представленыпараметры, управляющие выполнением методов. Некоторые из них относятсяк исключениям, тайм-ауту и отмене.

Page 242: Microsoft ASP.NET 2.0 AJAX

2 4 2 Глава 6. Обращение к серверным службам

Как упоминалось ранее, методы веб-служб могут связываться с различнымифункциями обратного вызова JavaScript — для успешного завершения, тайм-аута,исключений и отмены. Впрочем, сигнатуры этих функций несколько отличаются:

function methodCompleted(results, response, context)function methodTimeOut(results, context)function methodError(results, response, context)function methodAborted(results, context)

Параметры перечислены в табл. 6.5.

Таблица 6.5. Параметры функций обратного вызова для методов веб-служб

Параметр Описание

Results Возвращаемое значение метода веб-службы, десериализованноеинфраструктурой Atlas

Response Ответ на запрос в виде объекта JavaScript Sys.Net.XmlHttpExecutor.Содержит свойства statusCode, isComplete, isTimedOut и data

Context Объект JavaScript, переданный в качестве пользовательского контекстапри вызове метода

Параметр results берется из объекта, на который ссылается параметр response.Если метод веб-службы инициирует исключение, то он возвращает управле-

ние, а Atlas выполняет обработчик ошибки (если таковой есть). В этом случаеобъект response отсутствует, а в параметре results передается объект JavaScriptSys.Net.MethodRequestError с тремя свойствами: message, stackTrace и exceptionType.

function methodError(results, response, context){

// Выводит сообщение, соответствующее серверному исключениюalert(results.get jnessage());

}

Интервал тайм-аута при выполнении метода задается в шестом аргументе.Например, следующая команда ограничивает время выполнения метода тремясекундами. После истечения заданного интервала запрос автоматически отменя-ется, после чего вызывается функция обратного вызова methodTimedOut:

IntroAtlas.WebServices.MyDataService.VeryLengthyTask(methodCompleted, methodTimedOut, null, null, null, 3000);

Наконец, пользователи могут отменять незавершенные запросы в интерак-тивном режиме:

// request - глобальная переменная JavaScriptrequest = IntroAtlas.WebServices.MyDataService.VeryLengthyTask(

methodCompleted, null, null, methodAborted);

Также можно разместить кнопку отмены где-то на странице, связанной с об-работчиком onclick:

function abortRequestO{

request.abortO;}

Page 243: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 4 3

Пакетные обращения к веб-службамКаждый вызов веб-службы требует круговой пересылки данных (отправка + при-ем). Хотя цикл пересылка данных Atlas облегчена по сравнению с классическимвозвратом данных, она все равно остается ресурсоемкой операцией, которая мо-жет отрицательно сказаться на работе вашего приложения.

В Atlas можно приказать сетевому уровню клиентской стороны упаковыватьнесколько вызовов в одну круговую пересылку. Библиотека Microsoft AJAX ав-томатически упаковывает все запросы, по отдельности выполняет их на сервере,а затем заново упаковывает результаты перед отправкой их браузеру.

Для включения режима пакетных вызовов потребуется дополнительный об-работчик HTTP, который должен быть активизирован в файле web.config прило-жения:

<httpHandlers><add verb="*" path="atlasbatchcall.axd"

type="Microsoft.Web.Services.MultiRequestHandler" />

</httpHandlers>

Кроме того, в каждую страницу Atlas, в которой предполагается использова-ние пакетных вызовов, включается следующий код XML Script:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><webRequestManager enableBatching="true" batchSize="5"

batchDelay="1000" /></components>

</page></script>

Следующий код JavaScript создает четыре вызова метода веб-службы. В дан-ном примере вызывается один и тот же метод одной службы, однако вы можетевызывать любые методы других служб:

<script 1anguage="javascript" type="text/javascript">function findCustomersO{

IntroAtlas.WebServices.MyDataService.LookupCustomer("alfki",findCustomersCompleted, null, null, null, null, null, 1);

IntroAtlas.WebServices.MyDataService.LookupCustomer("bottm",findCustomersCompleted, null, null, null, null, 1);

IntroAtlas.WebServices.MyDataService.LookupCustomer("godos",findCustomersCompleted, null, null, null, null, 1);

IntroAtlas.WebServices.MyDataService.LookupCustomer("magaa",findCustomersCompleted, null, null, null, null, 1);

}function findCustomersCompleted(results, response, context){

debug.dump(results);debug.trace("<hr>");

}</script>

Page 244: Microsoft ASP.NET 2.0 AJAX

2 4 4 Глава 6. Обращение к серверным службам

Для каждого вызова указывается функция обратного вызова для успешногозавершения и приоритет. Чтобы вызов веб-службы мог быть включен в пакет,он должен обладать ненулевым приоритетом — то есть 1 (нормальный) или2 (низкий). Вызовы с максимальным приоритетом (0) никогда не объединя-ются в пакеты, а выполняются немедленно. Обратите внимание: по умолчаниювызову веб-метода присваивается максимальный приоритет. Другими слова-ми, для использования пакетного вызова необходимо явно задать ненулевойприоритет.

Параметр batchSize в коде XML Script указывает количество вызовов, объ-единяемых в пакет. Если он равен 5, четыре вызова (как в findCustomers) потре-буют одной круговой пересылки данных (рис. 6.9).

Попробуйте изменить значение batchSize на 2 и перезапустите страницу. Ре-зультат внешне не изменится, но для завершения страницы теперь потребуютсядва цикла пересылки данных.

Рис. 6.9. Объединение пакетных вызовов веб-служб в один цикл пересылки

Page 245: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 4 5

При возвращении из запроса функция обратного вызова будет вызвана поодному разу для каждого пакетного вызова. С точки зрения разработчика про-граммирование пакетных вызовов ничем не отличается от программированияодиночных вызовов веб-методов.

ВНИМАНИЕПакетная подсистема группирует вызовы веб-методов из любых точек приложения.В предыдущем примере четыре последовательных вызова инициировались однимщелчком на кнопке. А если бы на странице находились четыре кнопки, каждая из кото-рых инициирует один вызов веб-службы? Что произойдет в этом случае? Будет ли па-кетная подсистема неопределенно долго ожидать, пока пользователь щелкнет на всехчетырех кнопках? Конечно, нет.В коде XML Script, настраивающем пакетный вызов для отдельных страниц, такжеможно задать значение свойства batchDelay. Свойство определяет, как долго клиент-ский сетевой уровень будет ожидать накопления запросов веб-служб и заполненияпакета, прежде чем приступить к пересылке. Задержка по умолчанию равна 500 мс.В ситуации с четырьмя кнопками это означает, что если пользователь щелкает, скажем,дважды менее чем за полсекунды, то в пакет будут объединены два вызова; в против-ном случае эти вызовы будут отправлены раздельно. Обратите внимание: в предыду-щем примере свойство batchDelay было задано равным 1000 мс.

Механика вызова веб-службыЛюбая веб-служба, зарегистрированная в ScriptManager, заставляет Atlas загру-зить класс-посредника JavaScript при загрузке веб-страницы в браузере. Рассмот-рим следующий серверный сценарий:

<atlas:ScriptManager ID="scriptManagerl" runat="server"><Services>

<asp:ServiceReference Path="~/WebServices/MyDataService.asmx" />

</Services></atlas:ScriptManager>

Элемент <asp:ServiceReference> — удобная конструкция, которая вставляетв клиентскую страницу следующий код XML Script:

<page xmlns:script="http://schemes.microsoft.com/xml-script/2005"><references>

<add src="../WebServices/MyDataService.asmx/js"onscriptload="IntroAtlas.WebServices.MyDataService.path =

'/IntroAtlas/WebServices/MyDataService.asmx'" /></references>

</page>

Атрибут OnScriptLoad указывает на фрагмент сценарного кода, выполняемыйпри загрузке сценария, на который указывает атрибут src. В данном примере онзадает путь к веб-службе (информация, которая не была жестко закодированав сгенерированном классе-посреднике).

Page 246: Microsoft ASP.NET 2.0 AJAX

2 4 6 Глава 6. Обращение к серверным службам

СОВЕТСсылки на сценарные файлы в приложениях Atlas лучше всего объявлять на деклара-тивном уровне. Для этого потребуется небольшой объем кода XML Script:<script type="text/xml-script"><page>

<references><add src="..." onscriptload="..." />

</references></page>

</script>

Более аккуратная и абстрактная, но полностью эквивалентная запись становится воз-можной при использовании секции <Scripts> компонента ScriptManager.<asp:ScriptManager ID="scriptManagerl" runat="server"><Scripts>

<asp:ScriptReference path="..." onscriptload="..." /></Scripts>

</asp:ScriptManager>

В обоих случаях атрибут OnScriptLoad определяет код, который должен выполнятьсяпосле полной загрузки указанного сценария.

После того как ссылка на веб-службу будет создана, вы можете на программномуровне обращаться к веб-методам, вызывая методы класса-посредника JavaScript.Каждый вызов метода веб-службы приводит к тому, что на URL веб-службы от-правляется запрос с дополнительным строковым параметром mn (сокращение от«method name», то есть «имя метода»), содержащим имя вызываемого метода:

http://localhost/IntroAtlas/WebServices/MyService.asmx?mn=LookupCustomer

Как видно из приведенного URL, при передаче запроса в виде операции GETвходные параметры присоединяются к URL. Но если запрос передается в видеоперации POST, входные параметры включаются в тело запроса. На рис. 6.10 по-казано тело запроса POST к веб-службе.

HTTP-обработчик Atlas для ресурсов .asmx перехватывает запрос и по пара-метру mn определяет, что перед ним вызов веб-службы Atlas. В общем случаеHTTP-обработчик Atlas для веб-служб особым образом обрабатывает два типаURL: с суффиксом /js и со строковым параметром mn. В первом случае гене-рируется код класса-посредника; во втором случае обработчик десериализуетвходные параметры, выполняет метод и готовит ответ. Ответ сериализуется в пред-ставление XML или JSON, после чего отправляется. Формат сериализации вы-бирается при помощи атрибута WebOperation метода веб-службы (по умолча-нию JSON).

[WebMethcC[WebOperation(true, ResponseFormatMode.Json, true);public Customer LookupCustomer(string id){

}

Page 247: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 4 7

Рис. 6.10. Тело запроса к веб-службе, переданного в формате операции POST

Конструктор атрибута WebOperation получает до трех параметров , перечис-ленных в табл. 6.6.

Таблица 6.6. Свойства атрибута WebOperation

Параметр Описание

GetVerbEnabled

ResponseFormat

SafeForCrossDomain

Логическое свойство, указывающее, допускает ли веб-методвызовы с использованием команды GET. В .NET FrameworkGET-вызовы веб-служб по умолчанию запрещены, поэтомузначение по умолчанию равно false

Формат сериализации данных для веб-метода. Допустимыезначения объединены в перечисляемый типResponseFormatMode: Json (0, по умолчанию) и Xml (1)

Логический признак, указывающий, может ли методвызываться в том случае, если веб-служба находитсяпод управлением другого приложения. По умолчаниюиспользуется значение false

Как выясняется , для вызова методов веб-служб из страниц Atlas потребуетсянекоторая инфраструктура .

Основные требования заключаются в том, чтобы конечные точки «понимали»J S O N и могли распознавать вызовы с суффиксом /js и строковым параметром mn.

Page 248: Microsoft ASP.NET 2.0 AJAX

2 4 8 Глава 6. Обращение к серверным службам

Конечно, Atlas не сможет вызвать произвольную веб-службу без некоторой рабо-ты с вашей стороны. Вскоре тема связывания Atlas с внешними веб-службамибудет рассмотрена более подробно.

Методы страниц AtlasКак упоминалось ранее, веб-службы в основном используются как механизмвызова серверного кода со стороны клиента. Это одна из причин, по которымв приложение приходится встраивать специальные функции (мостовые техноло-гии) для вызова реально используемых служб. Создание локальной веб-службы(то есть находящейся в том же приложении) потребует некоторой дополни-тельной работы. Вам придется написать класс кодового файла, а также конеч-ную точку .asmx для открытого доступа. Кроме того, необходимо знать атри-буты веб-методов и веб-служб. Наконец, ваш код станет доступен в Интернете,поэтому могут потребоваться дополнительные меры безопасности для защитывашей системы.

Методы страниц Atlas предоставляют «облегченную» альтернативу для напи-сания серверного кода, вызываемого из клиентских страниц.

Объявление методов страницМетоды страниц представляют собой открытые методы, определенные в классекодового файла и помеченные атрибутом WebMethod. Они преобразуют страни-цу Atlas в некое подобие сильно упрощенной веб-службы.

Пример метода страницы:using System.Web.Services;public partial class Samples_Ch06_PageMethods : System.Web.UI.Page{

protected void Page_Load(object sender, EventArgs e){

}[WebMethod;

public UserStatus CreateUser(UserData data){

}[WebMethod;public UserStatus DeleteUser(string userName){

}}

Как видите, в определении метода страницы может использоваться практиче-ски любой тип данных, будь то тип .NET Framework или тип, определяемыйпользователем. Все, что говорилось ранее о сериализации JSON для методов веб-служб, относится и к методам страниц.

Page 249: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 4 9

Кроме того, веб-методы могут определяться в виде встроенного кода в исход-ном файле .aspx:

<script type="text/C#" runat="server">[WebMethocTpublic UserStatus CreateUser(UserData data){

}[WebMethocTpublic UserStatus DeleteUser(string userName){

}</script>

Если вы используете Microsoft Visual Basic, замените значение атрибута typeна text/VB.

Если кодовый файл страницы Atlas содержит методы, помеченные атрибу-том WebMethod, компонент ScriptManager генерирует код, который напоминаеткласс-посредника для обычной веб-службы, однако использует фиксированноеимя класса:

<script type="text/javascript">var PageMethods = new functionO {var cm=Sys.Net.PageMethod.createProxyMethod;cm(this,"CreateUser","data");cm(this,"DeleteUser","userName");

}</script>

В этом примере CreateUser и DeleteUser — веб-методы, объявленные в классекодового файла, или в исходном файле .aspx. Как мы вскоре увидим, для обраще-ния к методам страниц следует вызывать методы класса-посредника PageMethods.

Вызов методов страницРанее в этой главе обсуждалась служба аутентификации и операция входа в систе-му. Служба аутентификации Atlas использует API принадлежности (membershipAPI) для проверки регистрационных данных. Тем не менее не существует средствAtlas (по крайней мере пока) для проверки пользователей на стороне клиента.Чтобы создать новую учетную запись пользователя без полного возврата дан-ных, можно внедрить элемент CreateUserWizard в элемент UpdatePanel. Такое ре-шение будет работать еще быстрее, если инкапсулировать нужную часть интер-фейса принадлежности в веб-службу уровня страницы. Представьте, что у васимеется фрагмент разметки HTML для создания формы регистрации пользова-телей. В ее нижней части находится кнопка, при помощи которой пользовательзавершает регистрацию и создает учетную запись:

<input type="button" value="Create User" onclick="createUser()" />

Пользовательский интерфейс показан на рис. 6.11.

Page 250: Microsoft ASP.NET 2.0 AJAX

2 5 0 Глава 6. Обращение к серверным службам

3 Creating a new user - Microsoft Internet Explorer _-_ @sFile Edit View Favorites Tools Help if

0 Ш ' i i Я Search ^Favorites ■ @ | | 0 1 - < ^ [ Й ] т [

Address Щ\ http://localhost: 1386/IntroAtlas/Samples/Ch06/WebServices/Crea v и Links >J

Sign Up for Your New Accou nt 4

User Name: DinoE

44

Password: Barely Acceptable

44

E-mail: [email protected]

44

Security Question: What follows 123?

44

Security Answer: 456

44

Create User

44

$s\ Done * J Local intranet

Рис. 6 .11 . Форма Atlas для создания новой учетной записи пользователя,с расширителем PasswordStrength в поле ввода пароля

Метод createUser выглядит примерно так:<script language="javascript" type="text/javascript">function createUserO{

// Получение ссылок на поля вводаvar user = $("UserName");var pswd = $("Password");var email = $("EmaiI");var question = $("Question");var answer = $("Answer");// Подготовка входных данных для метода страницьvar data = new UserDataO;data.UserName = user.value;data.Password = pswd.value;data.Email = email.value;data.Question = question.value;data.Answer = answer.value;// Вызов метода страницьdebug.clearTraceO;Pagefiethods.CreateUser(data, createUserComplete);

}function createUserComplete(results){

debug.trace("<hr>");debug.dump(results);

</script>

Page 251: Microsoft ASP.NET 2.0 AJAX

Использование веб-служб 2 5 1

Функция упаковывает входные данные в объект UserData — класс опреде-ляется в кодовом файле и сериализуется в объект JavaScript благодаря помощиScriptManager. Метод страницы CreateUser создает нового пользователя при по-мощи объекта Membership и возвращает объект UserStatus с кодом статуса и опи-санием:

public class UserData{

public string UserName;public string Password;public string Email;public string Question;public string Answer;

}public class UserStatus{

public MembershipCreateStatus StatusCode;public string Description;

}public partial class Samples_Ch06_CreateUser : System.Web.UI.Page{

[WebMethod;public UserStatus CreateUser(UserData data){

MembershipCreateStatus code;Membership.CreateUser(data.UserName, data.Password,

data.Email, data.Question, data.Answer, true,out code);

UserStatus status = new UserStatusO;status.StatusCode = code;status.Description = code.ToStringO;

return status;}

}

При завершении метода JavaScript CreateUser функция обратного вызова по-лучает управление и выводит содержимое возвращенного объекта. На рис. 6.12показано, что произойдет, если введенный пароль окажется недостаточно силь-ным.

Разрешение и выполнение методов страницЧтобы вызвать метод страницы, необходимо сначала включить поддержку моду-ля HTTP ScriptModule в файле web.config приложения:

<httpModules><add name="ScriptModulе" type="Microsoft.Web.Services.ScriptModule"/>

</httpModules>

Page 252: Microsoft ASP.NET 2.0 AJAX

2 5 2 Глава 6. Обращение к серверным службам

Рис. 6.12. Неудачная попытка создания учетной записи

Если страница вызывает только «обычные» методы веб-служб, этот модуль необязателен. Модуль HTTP перехватывает событие приложения PostMapRequest-Handler. Данное событие указывает, что конвейер ASP.NET успешно определилобъект обработчика HTTP, который, в конечном итоге, будет обслуживать теку-щий запрос. Если объект является производным от Page, модуль регистрируетспециализированный обработчик для события страницы PreRenderComplete.

Обработчик события проверяет отправленные данные и ищет в них пару скры-тых полей __serviceMethodName и _serviceMethodParams. В них хранится имяи параметры метода, вызываемого для обслуживания запроса. Метод выполняет-ся и передает возвращаемое значение; при десериализации входных данных и се-риализации выходных данных используется формат JSON.

Page 253: Microsoft ASP.NET 2.0 AJAX

Связь с внешними веб-службами 2 5 3

ПРИМЕЧАНИЕСостав удаленных служб, которые могут использоваться в приложениях Atlas, не огра-ничивается веб-службами ASP.NET (конечные точки .asmx). Приложения Atlas такжемогут работать с серверными веб-службами на базе WCF (Windows CommunicationFoundation), одного из краеугольных камней будущей платформы .NET Framework 3.0.Технология WCF (ранее известная под кодовым обозначением «Indigo») представля-ется как совокупность ряда существующих коммуникационных технологий Microsoft(например, MSMQ, .NET Remoting и Enterprise Services), объединенных и расширен-ных в единую программную модель. Службы WCF могут использоваться в тех ситуа-циях, в которых сегодня используются веб-службы ASP.NET, а также в ситуациях,когда уместно применение других коммуникационных технологий. Модель WCF независит от нижележащих коммуникационных протоколов и позволяет приложениямвзаимодействовать друг с другом на базе открытых стандартов и протоколов.Технология Windows Communication Foundation будет выпущена в составе .NETFramework 3.0 — одной из базовых частей операционной системы Windows Vista. Онатакже будет доступна для Windows XP и Windows Server 2003. Для проверки моде-ли взаимодействия WCF в приложениях Atlas потребуется по меньшей мере NETFramework версии Beta 2. За дополнительной информацией о WCF обращайтесь насайт http://wcf.netfx3.com.В любом случае помните, что поддержка WCF не является обязательной для работыASP.NET Atlas. Даже если она недоступна на сервере, приложения Atlas все равно смо-гут пользоваться веб-службами ASP.NET.

Связь с внешними веб-службамиДо настоящего момента мы рассматривали только веб-службы, находящиесяв одном приложении с вызывающей страницей. Но что, если веб-служба явля-ется частью другого веб-приложения или работает на другой серверной плат-форме?

Проблема имеет разные решения в зависимости от того, распространяетсяли контроль разработчика на обе стороны канала связи или только на клиент-скую сторону. В первом случае существует обходное решение, позволяющееиспользовать междоменные вызовы в Atlas. Во втором случае потребуется уча-стие посредника, связывающего вызывающую страницу с произвольным веб-сервером.

Вызов нелокальных веб-служб AtlasКлючевой фактор заключается в том, что для прямого обращения к веб-службеиз Atlas веб-сервер конечной точки должен удовлетворять ряду критериев. В ча-стности, конечная точка должна поддерживать формат JSON, а также уметь об-рабатывать суффикс /js и параметр mn в строке запроса.

Самый простой вариант выполнения необходимых условий — если целеваявеб-служба находится под управлением другого приложения с поддержкой Atlas.Очевидно, это возможно только в том случае, если веб-служба входит в составвызывающего приложения Atlas или если веб-сервер конечной точки принадле-жит той же группе разработки.

Page 254: Microsoft ASP.NET 2.0 AJAX

2 5 4 Глава 6. Обращение к серверным службам

Настройка веб-служб во внешнемприложении AtlasЕсли вы хотите развернуть веб-службы, вызываемые из Atlas, в другом веб-при-ложении или сервере, вам необходимо создать второе приложение ASP.NET 2.0,в котором выполняются как минимум следующие условия:I включение поддержки Atlas в файле web.config. В частности, это означает за-мену обработчика HTTP .asmx и включение веб-служб;установка сборки Microsoft.Web.Atlas в папке Bin.После этого остается лишь обратиться к веб-службе из страницы по полному

удаленному URL. Тем не менее попытка вызова веб-службы, скорее всего, завер-шится неудачей.

Дело в том, что реализации XmlHttpRequest в некоторых браузерах по умолча-нию запрещают междоменные вызовы. Так как объект, от которого исходит вы-зов, спрятан где-то в недрах прикладной среды, вам как веб-разработчику будетнелегко найти нужную точку для внесения изменений. В том, что касается Atlas,междоменные вызовы разрешаются посредством регистрации нового обработчи-ка HTTP в целевом веб-приложении и небольших изменений в коде класса веб-службы. HTTP-обработчик Atlas, предназначенный для междоменных вызовов,называется iframecall.axd:

<httpHandlers><add verb="*"

path="iframecall.axd"type="Microsoft.Web.Services.IFrameHandler" />

</httpHandlers>

Также необходимо проследить за тем, чтобы веб-методы были помечены ат-рибутом WebOperation, у которого третий параметр (SafeForCrossDomain) заданравным true:

[WebMethod;[WebOperation(true, ResponseFormatMode.Json, true);public Customer LookupCustomer(string id){

}

Обработчик iframecall.axd и сопутствующий класс JavaScript (Sys.Net.lFrame-Executor в файле atlas.js) вызывают веб-службу без использования объекта Xml-HttpRequest. Вместо этого они выполняют междоменные вызовы, загружая URLвеб-службы в скрытом фрейме как сценарный код.

Возможные измененияКласс IFrameExecutor работает в Atlas CTP (Community Technology Preview) заиюль 2006 года, но может и не работать в будущих версиях. Возможно, синтак-сис, основанный на iframecall.axd, сохранит работоспособность, но базовая техно-логия междоменных вызовов, скорее всего, значительно изменится.

Page 255: Microsoft ASP.NET 2.0 AJAX

Связь с внешними веб-службами 2 5 5

Основная схема обращения к веб-службам за пределами локального приложе-ния базируется на сетевых исполнителях. Сетевой исполнитель (network executor)представляет собой класс JavaScript, производный от Sys.Net.WebRequestExecutor.Этот класс знает, как организовать выполнение веб-запроса по заданному URL.На данный момент в библиотеку Microsoft AJAX включены два исполнителя:XMLHttpExecutor и IFrameExecutor. Идея заключается в создании собственного ме-ханизма междоменных вызовов, для которого вы выбираете способ упаковкиданных и проведения запроса.

Подключение к сторонним веб-службам в ИнтернетеМожет оказаться, что веб-служба, к которой вы хотите подключиться из прило-жения Atlas, не является ни локальной, ни работающей на базе Atlas. Еще разстоит подчеркнуть, что все описанные ранее средства и приемы не сработают,если вы захотите использовать страницу для размещения заказов через службуAmazonWeb (произвольно взятый пример типичной сторонней службы, не бази-рующейся на Atlas). Что делать в этом случае?

Технология мостов (bridge) Atlas позволяет разработчику создавать программ-ные шлюзы к веб-службам в Интернете. Поскольку мостовой код работает внут-ри вызывающего приложения объект, браузер взаимодействует только с однимсервером. Мостовой код, в свою очередь, может взаимодействовать с любой веб-службой, доступной в Интернете, и возвращать данные клиентской странице.Мостовой код является основной технологией для создания гибридных прило-жений, то есть приложений, объединяющих данные от нескольких удаленныхисточников и представляющих их клиентам в удобной форме.

Конфигурация и настройкаШлюз Atlas к сторонним веб-службам представляет собой файл с расширением.asbx. Файл содержит данные XML с описанием вызова веб-службы. Основнаяпричина для наличия подобных посредников заключается в том, что реальныевеб-службы могут получать параметры не в виде отдельных величин, а требоватьпередачи объекта. В свою очередь, объект может включать свойства, также отно-сящиеся к сложным типам. Следовательно, построение запросов и разбор воз-вращаемых значений могут потребовать некоторой работы по программирова-нию. Здесь в дело вступают мостовые файлы (.asbx).

Для подключения к сторонней веб-службе из Atlas необходимо зарегистриро-вать расширение .asbx в IIS (Internet Information Services) и поручить ASP.NETего обработку. Чтобы посмотреть, как это делается, откройте диалоговое окноконфигурации в целевой виртуальной папке IIS, перейдите на вкладку Mappingsи просмотрите содержимое диалогового окна Add/Edit Application Extension Map-ping (рис. 6.13).

Если проект Atlas был создан на базе шаблона Visual Studio 2005, расширение.asbx уже присутствует и зарегистрировано за aspnet_isapi.dll. В противном слу-чае отредактируйте отображения и выполните привязку ресурсов .asbx в расши-рении ASP.NET ISAPI (Internet Server Application Programming Interface).

Page 256: Microsoft ASP.NET 2.0 AJAX

2 5 6 Глава 6. Обращение к серверным службам

Рис. 6.13. Регистрация расширения .asbx в IIS

Что делать, если ваш сайт работает на внешнем хостинге? Что, если вы необладаете правами администратора? Альтернативный способ использованиямостовой технологии основан на применении туннелей. На практике вам при-дется настроить модуль HTTP, предоставляемый Atlas, который анализирует всевходящие запросы и перенаправляет запросы, содержащие строку "bridge.axd",указанному вами ресурсу .asbx. Например, запрос MyServiceBridge.axd преобра-зуется в запрос к MyService.asbx при помощи модуля Atlas BridgeModule, конфи-гурация которого выглядит так:

<httpModules><add name="BridgeModule" type="Microsoft.Web.Services.BridgeModule" />

</httpModules>

Создание и выбор имени мостового файла (например, Xxx.asbx) происходитпо обычным правилам. Затем, если включена поддержка туннелирования, мосто-вой файл переименовывается в XxxBridge.axd. В только что рассмотренном при-мере мостовому файлу было присвоено имя MyServiceBridge.axd. BridgeModuleотсекает «MyService» и присоединяет суффикс «.asbx». Сформированное имямостового файла MyService.asbx будет реально вызываться при поступлении за-просов к MyServiceBridge.axd.

Зачем это все нужно? При внешнем хостинге вы не обладаете доступом к ад-министративной панели IIS, а следовательно, не сможете добавить запись *.asbxв список отображаемых расширений IIS. В стандартной конфигурации IIS необрабатывает запросы к ресурсам .asbx, и любые попытки таких запросов завер-шатся неудачей. Механизм туннелирования попросту «обманывает» IIS и за-ставляет сервер перенаправить запрос ASP.NET — где существует компонент,умеющий обрабатывать мостовые файлы.

Далее также необходимо зарегистрировать обработчик HTTP для мостовыхфайлов:

<httpHandlers><add verb="*" path="*.asbx"

type="Microsoft.Web.Services.ScriptHandlerFactory" />

</httpHandlers>

Page 257: Microsoft ASP.NET 2.0 AJAX

Связь с внешними веб-службами 2 5 7

Если вы планируете использовать мостовые файлы непосредственно в прило-жении, мостовой обработчик не потребуется. Если все страницы на базе мостовнаходятся в одной вложенной папке, эту настройку также можно переместитьв файл web.config уровня папки.

Мостовые файлыКак упоминалось ранее, мостовой файл Atlas представляет собой файл XML с рас-ширением .asbx. В мостовом файле вы объявляете, как следует подключаться к уда-ленной веб-службе и как будут обрабатываться возвращаемые данные.

В наши дни многие популярные веб-службы поддерживают два протоколавызова: SOAP и POX. Хорошо известный протокол SOAP (Simple Object AccessProtocol) определяет структуру сообщений, используемых в распределеннойсреде обмена данных, на базе XML. Протокол SOAP используется веб-службамидля взаимодействия с вызывающей стороной. Формат POX (Plain Old XML) со-стоит из команды GET, у которой все параметры перечисляются в строке запроса.Почему многие популярные веб-службы, включая MSN Search и Amazon, в нашидни используют POX? Ответ состоит из одного слова: доступность. Избавле-ние от сложностей, связанных с SOAP, позволяет работать с веб-службами набазе POX более широкому кругу пользователей. (Не обманывайтесь, протоколSOAP отнюдь не тривиален… Просто с ним удобнее работать, чем с его предше-ственниками.)

В свете сказанного у приложений Atlas есть два возможных способа работыс веб-службами.

I Утилита wsdl.exe из Visual Studio 2005 генерирует для веб-службы класс-по-средник .NET. Разработчик помещает класс в папку App_Code приложенияAtlas и создает мост, связывающий страницы с классом-посредником. Классмоста фактически определяет программный интерфейс JavaScript, которыйбудет использоваться вашими страницами для обращений к классу-посредни-ку .NET. Класс-посредник использует SOAP для размещения вызовов.

I Если вы предпочитаете решение на базе POX, классы-посредники .NET непонадобятся. Вы просто создаете мостовой файл и строите программный ин-терфейс JavaScript для страниц Atlas. Далее Atlas обрабатывает содержимоемостового файла и размещает запросы GET для вызова веб-методов.Давайте посмотрим, как создать мостовой файл, который использует POX

для вызова веб-службы Amazon и получения информации о книгах.

Построение мостового файла для веб-службы AmazonВеб-служба Amazon позволяет разработчикам веб-сайтов работать на программ-ном уровне с каталогом Amazon, поисковой системой, корзиной и коммерческиминструментарием. Необходимый пакет разработчика можно загрузить по сле-дующему адресу:

http://associates.amazon.com/exec/panama/associates/join/developer/kit.html

Для использования веб-службы вам потребуется маркер (token) разработчи-ка; страница упрощает его получение. Чтобы получить информацию о книгах,

Page 258: Microsoft ASP.NET 2.0 AJAX

2 5 8 Глава 6. Обращение к серверным службам

написанных заданным автором, необходимо отправить вызов по следующемуURL с добавлением нескольких параметров:

http://xml.amazon.com/onca/xml2

Некоторые из часто используемых параметров перечислены в табл. 6.7.

Таблица 6.7. Параметры поиска книг веб-службой Amazon

Параметр ОписаниеT Тег запроса (должен быть равен «webservices-20»)F Формат вывода (должен быть равен «xml»)Page Запрашиваемая страница (по умолчанию 1)Sort Тип сортировки (допустимые значения: +salesrank, +daterank

и +titlerank (алфавитная)dev-t Маркер разработчикаMode Каталог, в котором ведется поиск (должен быть равен books)Type Объем информации, упакованной в ответе (допустимые значения:

lite и heavy)keywordSearch Строка запроса

В мостовом файле определяется программный интерфейс для возможностейвеб-службы. Например, можно определить «обертку» JavaScript с методом Find,который получает ключевое слово поиска и возвращает данные. Соответствую-щий мостовой файл будет выглядеть так:

<bridge namespace="IntroAtlas" className="AmazonPox" ><proxy type="Microsoft.Web.Services.BridgeRestProxy"

serviceUrl="http://xml.amazon.com/onca/xml2" /><method name="Find">

<input><parameter name="t" value="webservices-20" /><parameter name="mode" value="books" /><parameter name="type" value="lite" /><parameter name="f" value="xml" /><parameter name="page" value="l" /><parameter name="sort" value="+salesrank" /><parameter name="dev-t" value='7 appsettings : AmazonToken %" /><parameter name="KeywordSearch" />

</input></method>

</bridge>

Атрибуты namespace и classname тега <bridge> определяют полное имя по-лученного класса JavaScript. В элементе <ргоху> атрибут type обозначает ком-понент, ответственный за выполнение удаленного вызова по поручению вашегоприложения. Атрибут serviceURL задает URL, которому адресуется вызов.

Элементы <method> определяют программный интерфейс мостового класса.Все методы, определяемые в этой секции, включаются в «обертку» JavaScript

Page 259: Microsoft ASP.NET 2.0 AJAX

Связь с внешними веб-службами 2 5 9

IntroAtlas.AmazonPox, которая будет использоваться в ваших страницах Atlas. Ко-нечно, количество элементов <method> может быть любым.

Приведенный сценарный код определяет метод Find, получающий до восьмипараметров. Все перечисленные параметры (и только они) включаются в коман-ду GET, отправляемую на URL службы. Первые шесть параметров имеют фик-сированные значения. Значение седьмого параметра (dev-t) читается из секции<appSettings> файла web.config.

<appSettings><add key="AmazonToken" value="..." />

</appSettings>

На этой стадии все готово к написанию кода JavaScript, который вызываетвеб-службу Amazon и получает информацию о книгах, написанных заданным ав-тором. Какую информацию, спросите вы? В этом-то все и дело!

Получение данных Amazon через мост AtlasВ следующей странице при создании ссылки на мостовой файл используетсясинтаксис, уже использовавшийся ранее для локальных веб-служб. На страницерасположено текстовое поле и кнопка. Пользователь вводит имя автора в тексто-вом поле и щелкает на кнопке, чтобы найти книги данного автора.

<form id="forml" runat="server"><asp:ScriptManager ID="scriptManagerl" runat="server">

<Services><asp:ServiceReference Path="-7WebServices/Amazon.asbx" />

</Services></asp:ScriptManager>

<h3>Find an author: <asp:TextBox ID="TextBoxl" runat="server" /></h3><input type="button" value="Go" onclick="findBooks()" /><hr /><asp:Panel runat="server" ScrollBars="Auto" Height="300px">

<asp:label runat="server" ID="0utput" /></asp:Panel>

</form>

Функция findBooks выглядит так:<script language="javascript" type="text/javascript">

function findBooks(){

var author = $("TextBoxl").value;IntroAtlas.AmazonPox.Find( {KeywordSearch:author},findBooksCompleted, null, findBooksError);

}function findBooksCompleted(results, response, context){

debug.dump(results);}function findBooksError(results, response, context){

debug.trace(results.get_message());}

</script>

Page 260: Microsoft ASP.NET 2.0 AJAX

2 6 0 Глава 6. Обращение к серверным службам

Запустите страницу. Введите в текстовом поле строку Dino Esposito и щелк-ните на кнопке.

На рис. 6.14 показан результат.

Рис. 6.14. Мостовой файл получает информацию от веб-службы Amazon

Такое решение работает, но можно ли честно сказать, что именно на это мыи рассчитывали? Возвращаемое значение представляет собой огромную строкуXML, в которой вся запрашиваемая информация упакована в соответствии сосхемой, определенной разработчиками Amazon. Как преобразовать полученнуюстроку в формат, удобный для пользователя?

Преобразование ответа веб-службыПо умолчанию считается, что ответ веб-службы представляет собой поток дан-ных JSON, и он разбирается в объект JavaScript. Впрочем, это предположение необязательно истинно. Amazon или любая другая сторонняя веб-служба знаето ваших предположениях. В конечном итоге данные будут приняты правильно,но это не значит, что их можно будет немедленно использовать. Добавляя сек-цию <transforms> в мостовой файл, вы приказываете инфраструктуре Atlas обра-ботать возвращаемое значение и построить объект JavaScript, с которым вам бу-дет удобнее работать для представления результатов пользователю.

Page 261: Microsoft ASP.NET 2.0 AJAX

Связь с внешними веб-службами 2 6 1

Для последующей обработки возвращаемого значения веб-службы могут ис-пользоваться различные преобразователи (transformers). В Atlas имеется несколь-ко встроенных преобразователей, перечисленных в табл. 6.8.

Таблица 6.8. Встроенные мостовые преобразователи

Тип ОписаниеObjectMapperBridgeTransformer Если возвращаемое значение представляет собой объект,

преобразователь отображает свойства возвращенногообъекта на пользовательский объект

XmlBridgeTransformer Преобразователь обрабатывает возвращенные данныес помощью XmlSerializer и получает строку XML,представляющую выходные данные

XPathBridgeTransformer Преобразователь использует запросы XPath дляизвлечения данных из строки ответа и построенияпользовательского объекта

XsltBridgeTransformer Преобразователь применяет таблицу стилей XSLTк документу XML, представляющему возвращаемыеданные

Следующий пример показывает, как разобрать строку XML, полученнуюот веб-службы Amazon, с извлечением содержательной информации запросамиXPath. Чтобы написать преобразователь, необходимо хорошо знать формат ответа.

В ответах Amazon обычно используется следующий формат:<ProductInfo>

<TotalResults> ... </TotalResults><TotalPages> ... </TotalPages><Details>

<Asin> ... </Asin><!-- Другие теги -->

</Details><Details>

</Details>

</ProductInfo>

Элемент <TotalResults> определяет количество записей, полученных при по-иске, а элемент <TotalPages> — количество страниц, которые для этого потребу-ются, с размером страницы по умолчанию. Наконец, массив блоков <Details> со-держит информацию об отдельных предметах — книгах, альбомах и т. д. Каждыйблок <Details> содержит, по крайней мере, один тег <Asin> c идентификаторомпредмета, используемым службой Amazon. Для книг он совпадает с кодом ISBN.

Следующий преобразователь превращает ответ в массив более простых объ-ектов JavaScript:

<transforms><transform type="Microsoft.Web.Services.XPathBridgeTransformer">

<data>

Page 262: Microsoft ASP.NET 2.0 AJAX

2 6 2 Глава 6. Обращение к серверным службам

attribute name="selector" value="Details" />dictionary name="selectedNodes">

<item name="ISBN" value="Asin" /><item name="Title" value="ProductName" /><item name="Publisher" value="Manufacturer" /><item name="CoverPicture" value="ImageUrlSniall" />

</dictionary></data>

</transform></transforms>

Атрибут selector приказывает XPath выбрать заданный узел — в данном слу-чае Details. Затем словарь selectedNodes выбирает множество узлов, корень кото-рого находится в выбранном узле. В результате выбираются все узлы с именемDetails. Преобразователь создает словарь JavaScript, объекты которого обладаютчетырьмя свойствами: ISBN, Title, Publisher и CoverPicture. Каждое свойство ото-бражается на конкретный элемент в иерархии n-го элемента <Details>. На этойстадии значение, которое передается функции обратного вызова, назначеннойдля завершения метода, представляет собой массив объектов JavaScript с указан-ными четырьмя свойствами. Теперь на его основе можно строить пользователь-ский интерфейс (рис. 6.15).

Рис. 6.15. Простой, но эффективный пример гибридного приложения

Page 263: Microsoft ASP.NET 2.0 AJAX

Заключение 2 6 3

function findBooksCornpleted(results, response, context){

var builder = new Sys.StringBuilder("<table>");for(i=0; i<results.length; i++){

builder.append("<tr>");builder.append("<td><img src='");bui1der.append(results[i].CoverPicture);builder.appendC' /></td>");builder.append("<td>");builder.append(results[i].ISBN);bui1der.append("<br/><b>");builder.append(results[i].Title);bui1der.append("</b><br/>");bui1der.append(results[i].Publisher);builder.append("</td></tr>");

}bui1der.append("</table>");$("Output").innerHTML = builder.toStringO ;

}

Кэширование данныхИногда получение ответа от сторонних веб-служб требует времени — из-за неиз-бежных сетевых задержек или по другим причинам. Таким образом, результатывызова веб-служб есть смысл кэшировать, чтобы они оставались доступнымив течение некоторого интервала времени.

Включая следующий сценарий в мостовой файл, вы приказываете Atlas ис-пользовать для получения данных указанный вами компонент. Если компонентне возвращает данные (то есть кэшированный результат отсутствует), Atlas про-должает действовать по обычной схеме и инициирует вызов:

<bridge namespace="IntroAtlas" className="AmazonPox" >

<caching><cache type="IntroAtlas.AmazonPoxCacheObject" />

</caching></bridge>

Пользовательский класс реализует интерфейс IBridgeRequestCache, а его ос-новные функции сводятся к простому сохранению полученных данных. Классотвечает за выбор способа хранения (статические члены класса, файл на диске,база данных) и за определение срока, в течение которого данные считаютсядействительными. Интерфейс IBridgeRequestCache определяет три метода: Put,Lookup и Initialize. Метод Put сохраняет данные; метод Lookup проверяет действи-тельность данных и возвращает их.

ЗаключениеВеб-службы представляют собой компоненты, находящиеся под управлением веб-приложений, функции которых доступны с использованием стандартных прото-колов. Как это характерно для компонентной разработки, веб-службы работают

Page 264: Microsoft ASP.NET 2.0 AJAX

2 6 4 Глава 6. Обращение к серверным службам

по принципу «черного ящика»: их функциональность можно использовать мно-гократно, не беспокоясь о том, как реализована данная служба. В общем случаерекомендуется проектировать веб-службы так, чтобы они работали именно какслужбы, а не как типичные компоненты. Тем не менее в Atlas дело обстоит не-сколько иначе.

В приложениях Atlas веб-служба прежде всего является логически четкими эффективным способом выполнения действий на стороне сервера в ответ надействия клиента. Например, если потребуется заполнить клиентский элементданными, сгенерированными сервером, вы используете веб-службу. Но в этомслучае будет использоваться локальная веб-служба, определяемая и вызываемаяиз того же приложения. В Atlas определен специальный протокол для вызовавеб-служб. Предполагается, что конечная точка понимает формат JSON и умеетобрабатывать суффикс /js. Atlas сначала требует у веб-службы вернуть класс-по-средник JavaScript — по аналогии с тем, как в Visual Studio 2005 утилита wsdl.exeиспользуется для получения класса-посредника C# или Visual Basic. В приложе-ниях Atlas веб-службы работают только в контексте прикладной среды и могутпредставлять собой веб-службы ASP.NET, находящиеся под управлением при-ложений Atlas.

Значит ли это, что вы не сможете вызывать реальные веб-службы (такие, какAmazon или Google)? Вовсе нет. При помощи мостовой технологии страницуAtlas можно связать практически с любой веб-службой в Интернете. Программныйинтерфейс остается неизменным; схема всего лишь дополняется промежуточнымкомпонентом — мостовым файлом. Мостовой файл отвечает за предоставлениеинформации, достаточной для построения класса-посредника JavaScript приклад-ной средой. Трудно представить, что реально работающая веб-служба, которойничего не известно об Atlas, сможет сгенерировать класс-посредника JavaScriptнужным вам образом. Мостовой файл решает именно эту задачу. Наконец, мосто-вой файл также отвечает за упаковку возвращаемого значения в объект JavaScript.

В этой главе мы воспользовались мостовой технологией для приема инфор-мации о книгах с веб-сайта Amazon. После этого мы столкнулись с проблемойудобного вывода полученной информации.

Я выбрал вариант с построением таблицы HTML с использованием клиент-ского объекта StringBuilder. Если бы информация Amazon был доступна на моемсервере, было бы естественно воспользоваться Repeater или любым другим эле-ментом, связанным с данными. Именно клиентской привязке данных и будет по-священа следующая глава.

Page 265: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 7 Привязка данныхна стороне клиента

В этой главе:I Привязка данных к элементамI Расширенные функции

Подавляющее большинство веб-страниц предназначено для отображения дан-ных. В большинстве случаев данные читаются из серверного хранилища, оформ-ляются в разметку HTML и передаются ожидающему пользователю.

Все эти задачи обычно выполняются на сервере и требуют полного возвратаданных или по меньшей мере панели Atlas с частичным обновлением. Как былопоказано в главе 3, для простейшей реализации некоторой интерактивности в веб-страницах существует простой прием: включите элементы, связанные с данны-ми, в элемент UpdatePanel, а затем используйте стиль программирования, знако-мый по классической платформе ASP.NET.

Например, после размещения элемента GridView или Repeater на элементеUpdatePanel вы сможете легко отображать, фильтровать, выводить в страничномрежиме и сортировать любые данные — и за все это придется расплачиватьсялишь ценой асинхронного возврата данных Atlas. Чего еще можно пожелать?

Чтобы дать содержательный ответ на этот вопрос, давайте продолжим с того,на чем мы остановились в главе 6. В этой главе читатель узнал, как загрузитьданные с веб-сайта Amazon и оформить их в виде коллекции JavaScript на сторо-не клиента. Как организовать клиентское представление таких данных? Какиеэлементы необходимы для отображения перечислимых (enumerable) данных?

Настоящая глава посвящена клиентской привязке данных — то есть совокупно-сти средств и методов, используемых для формирования эффективных, управляе-мых данными пользовательских интерфейсов на JavaScript и HTML, в сочета-нии с дружественной моделью приложения классической платформы ASP.NET.

Привязка данных к элементамВ комплект поставки Atlas входит ряд элементов, связанных с данными, а такжеисточников данных, которые могут использоваться напрямую в браузерах безполного возврата данных. Механизм привязки данных (то есть процесс связы-вания данных с элементами) существует в двух вариантах: простом и сложном.

Page 266: Microsoft ASP.NET 2.0 AJAX

2 6 6 Глава 7. Привязка данных на стороне клиента

Простая привязка данныхПростой привязкой данных называется прямолинейное установление связи ме-жду одним значением в источнике данных и свойством элемента. Значениясвойств элементов могут задаваться как на программном, так и на декларатив-ном уровне.

Программный способ требует перехвата определенного события (например,загрузки страницы или изменения состояния элемента) и явного присваиваниянужных значений одному или нескольким свойствам элемента. При декларатив-ном способе разработчик должен «объявить» о своих намерениях в фрагментекода XML Script. Каждый элемент отслеживает свой набор привязок и исполь-зует эту информацию при выводе. Декларативная привязка выражается посред-ством XML Script, и в ней задействуются компоненты Atlas.

Коллекция <Bindings>Во всех компонентах Atlas определяется коллекция bindings. Элементы коллек-ции описывают связь между одним свойством компонента и одним свойствомуказанного источника данных. Источником данных может быть как тот же, таки другой компонент. Привязки пересчитываются автоматически (по умолча-нию) или программно. В последнем случае вы должны вызвать метод evaluatelnобъекта binding.

Каждая привязка представляется экземпляром класса Sys.Binding. Привязкиопределяются элементами <binding> в секции <bindings>. Атрибуты элементов<binding> перечислены в табл. 7.1.

Таблица 7.1 . Атрибуты элемента binding

Атрибут Описаниеautomatic Логическое значение, указывающее способ пересчета привязок

(автоматический или программный). По умолчаниюиспользуется значение true

dataContext Компонент-источник для операций привязки данныхdataPath Путь к свойству источника, используемому для привязкиdirection Направление привязки (допустимые значения — In, Out

и InOut). По умолчанию используется значение Inid Идентификатор привязки. Задается только в том случае, если

привязка должна использоваться в программном кодеproperty Имя свойства компонента, получающего связанные данныеpropertyKey Индекс или ключ целевого свойства (если применяется

индексирование)transformerArgument Необязательный аргумент, передаваемый преобразователюtransform Обработчик события, используемый в процессе преобразования

связанного значения

Page 267: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 6 7

Обратите внимание: привязка работает только между компонентами Atlasи только через свойства, определенные для компонентов Atlas. Таким образом,хотя вы можете инкапсулировать текстовое поле HTML или тег <span> в компо-ненте Atlas, значения, относящиеся к пользовательскому интерфейсу (такие, каксвойства стиля), не могут быть использованы для привязки.

Возможности привязки ограничиваются копированием значения исходногосвойства в целевое свойство. К исходному значению можно применить простыепреобразования, но нельзя выполнять действия или реализовать пользователь-скую логику. При настройке в автоматическом режиме (по умолчанию) при-вязка чрезвычайно полезна, поскольку ее пересчет гарантируется при каждомизменении свойства. Впрочем, при изменении свойства можно только задатьзначение. Для выполнения более сложных действий (скажем, обращения к сти-лю объекта или выполнению пользовательской логики) придется прибегнутьк классическим обработчикам событий.

Использование привязки для назначениясвойств элементаДопустим, на странице находится раскрывающийся список и надпись. Фрагментразметки ASP.NET:

<asp:DropDownList runat="server" ID="DropDownListl"><asp:Listltem Text="Red" /><asp:ListItem Text="Blue" /><asp:Listltem Text="Brown" /><asp:Listltem Text="Orange" />

</asp:DropDownList><hr /><asp:label runat="server" id="Label1" />

Чтобы определить привязку таким образом, чтобы текст надписи автоматиче-ски обновлялся при любых изменениях состояния раскрывающегося списка, при-дется написать небольшой фрагмент XML Script:

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><select id="DropDownListl" />

<label id="Labell"><bindings>

<bitiding dataContext="DropDownListl" dataPath="selectedValue"property="text" />

</bindings></label>

</components></page>

</script>

Атрибут property означает, что свойство text компонента Label должно обнов-ляться при каждом изменении свойства selectedValue компонента DropDownListl.В приведенном примере текст надписи изменяется сразу же после смены выде-ленной строки в раскрывающемся списке, отражая новое состояние выделения.

Page 268: Microsoft ASP.NET 2.0 AJAX

2 6 8 Глава 7. Привязка данных на стороне клиента

ВНИМАНИЕЕсли к тегам HTML, оформляемым в виде компонентов Atlas, применяются какие-ли-бо расширители, в дереве компонентов Atlas появятся дубликаты. В этом случае неследует добавлять определения компонентов самостоятельно; воспользуйтесь тем, чтомогут сделать за вас расширители. Допустим, надпись связана с содержимым текстово-го поля. В странице должен присутствовать следующий код:<textBox id="TextBoxl" />

Но если поле TextBox1 также связывается с расширителем, то приведенный текст по-явится дважды в клиентском исходном коде (там, где его вставите вы, и там, где еговставит расширитель) и runtime-среда Atlas выдаст сообщение об ошибке. Чтобыисправить ситуацию, опустите приведенное объявление; расширитель сгенерируетего за вас.Если позднее расширитель будет удален, вставьте объявление текстового поля вруч-ную, чтобы избежать ошибки «Object Not Found».

Что, если значение свойства-источника обновляется программным способом?Будут ли свойства связанного элемента обновляться автоматически? Давайтедобавим кнопку на страницу из нашего примера и посмотрим, что произойдет:

<asp:Button ID="Buttonl" runat="server" Text="Click"OnClientClick="SelectItem();return false;" />

Элемент ASP.NET Button инкапсулирует традиционную кнопку отправкиданных HTML. Однако возврат false в атрибуте OnClientClick позволяет обой-ти стандартное поведение инкапсулированной кнопки отправки данных и про-пустить отправку формы на сервер. В данном случае серверный элемент But-ton ведет себя как простая (не выполняющая отправку данных) клиентскаякнопка.

Для программной смены выделения в раскрывающемся списке потребуетсяследующий код:

<script type="text/javascript">function SelectItern О{

// Выделение любой строки (например, 3)$("DropDownListl").selectedlndex = 3;

}</script>

Интересный результат: выделение в раскрывающемся списке изменилось, носвязанный элемент не обновился. Почему это произошло?

Все компоненты Atlas используют метод raisePropertyChange для оповещениявсех связанных элементов об изменении своего состояния. В результате проис-ходит пересчет привязок. Для компонента Select оповещения об изменениях со-стояния происходят при выдаче события onchange, инициируются нижележащимобъектом DOM и при обновлении свойств, специфических для Atlas (например,data). Программное изменение selectedlndex не инициирует события onchangeв модели DOM и, как следствие, не обновляет привязки.

Page 269: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 6 9

Учтите: речь идет об особенности раскрывающихся списков и их реализациив DOM. В аналогичной ситуации элемент ТехШох будет работать иначе. Припрограммном задании содержимого в текстовом поле инициируется событие,обновляющее все привязки. В конечном итоге привязки пересчитываются тогда,когда источник данных оповещает об изменении состояния отслеживаемогосвойства. Каждый компонент Atlas организует оповещение об изменениях состоя-ния в соответствии со своей внутренней реализацией.

Использование преобразователейРанее уже говорилось о том, что привязка в основном сводится к присваиваниюисходного значения целевому свойству, к исходному значению можно применитьнекоторые преобразования. Для этой цели используются специальные обработ-чики событий, называемые преобразователями (transformers). Преобразовательопределяется со следующей сигнатурой:

function MyTransformer(sender, eventArgs){

}

Аргумент sender определяет объект Binding, инициировавший пересылку дан-ных. Аргумент eventArgs является экземпляром класса BindingEventArgs и ини-циализируется значением, хранящимся в целевом элементе. Свойства классаBindingEventArgs перечислены в табл. 7.2.

Таблица 7.2. Свойства класса BindingEventArgs

Свойство Описание

direction Направление текущей привязки: In, Out или InOuttargetPropertyType Тип целевого свойства в привязкеtransformerArgument Аргумент, передаваемый преобразователю. Значение задается

в элементе <binding> и должно быть постоянной величинойvalue Значение, задаваемое в результате привязки

Преобразователь может изменить значение свойства value в объекте Binding-EventArgs. При выходе из преобразователя содержимое value будет присвоено це-левому свойству привязки. Следующий преобразователь применяет форматиро-вание к строке, выбранной в раскрывающемся списке:

<script type="text/javascript">function FormatString(sender, eventArgs){

eventArgs.set_value("<t»Selected color is: </b>" +eventArgs.get_value());

}</script>

В Atlas определяется несколько встроенных преобразователей; они перечис-лены в табл. 7.3.

Page 270: Microsoft ASP.NET 2.0 AJAX

2 7 0 Глава 7. Привязка данных на стороне клиента

Таблица 7.3. Встроенные преобразователи

Функция Описание

Add

Compare

CompareInverted

Invert

Multiply

ToLocaleString

ToString

Прибавляет аргумент преобразователя к исходному значению.Свойство direction указывает, должно ли значение прибавлятьсяили вычитаться (вычитание применяется при direction=Out)

Сравнивает исходное значение с аргументом преобразователя,если он задан; в противном случае исходное значение вычисляетсякак логическая величина. Преобразователь не являетсядвусторонним и может использоваться только при direction=In

Проверяет, отличается ли исходное значение от аргументапреобразователя, если он задан; в противном случае исходноезначение вычисляется как логическая величина, а полученныйрезультат инвертируется. Преобразователь не являетсядвусторонним и может использоваться только при direction=In

Применяет оператор JavaScript ! к исходному значению.Учтите, что инвертирование null дает результат true

Умножает исходное значение на аргумент преобразователя

Преобразует исходное значение в строку с учетом локальногоконтекста. Преобразователь не является двусторонними может использоваться только при direction=In

Преобразует исходное значение в строку. Преобразовательне является двусторонним и может использоваться толькопри direction=In

Будет полезно кратко рассмотреть исходный код преобразователя Add. Этодаст вам более четкое представление о принципах работы преобразователей и обих потенциальных возможностях .

Sys.BindingBase.Transformers.Add = function(sender, eventArgs){

var value = eventArgs.get_value();if (typeof(value) != 'number') {

value = Number.parse(value);}

var delta = eventArgs.get_transformerArgument();if (!delta) {

delta = 1;}

if (typeof(delta) != 'number') { delta = Number.parse(delta);

if (eventArgs.get_direction() == Sys.BindingDirection.Out) { delta = -delta;

var newValue = value + delta;

Page 271: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 7 1

if (eventArgs.get_targetPropertyType() != 'number') {newValue = newValue.toStringO;

}eventArgs.set_value(newValue);

}

Как видите, преобразователь разбирает параметры, пытаясь получить значе-ние нужного типа — в данном случае это число. То же самое происходит и привозврате преобразованного значения. При несоответствии свойства целевоготипа новое значение сериализуется в строку.

ПРИМЕЧАНИЕЕсли преобразователь используется для выполнения математических операций со свя-занным значением, убедитесь в том, что вы работаете с допустимыми числами. Кромевызова Number.parse() для преобразования значения в число, сравните его с NaN —специальным значением класса Number, указывающим, что значение (как это ни пара-доксально) не является числом. Для проверки следует использовать глобальную функ-цию isNaN, определенную в языке JavaScript.

Сложная привязка данныхВ терминологии .NET Framework сложной привязкой данных называется си-туация, при которой с элементом связывается коллекция записей данных. При-вязка влияет на весь интерфейс элемента, а не только на отдельное свойство. Какправило, элемент при этом поддерживает шаблоны и предназначается для хра-нения дочерних элементов. В классической среде ASP.NET сложная привязкаданных поддерживалась элементами Repeater, DataList и DataGrid. В ASP.NET 2.0к ним присоединились новые элементы GridView, DetailsView и FormView.

Как отобразить содержимое коллекции объектов JavaScript, находящихся настороне клиента, — например, результаты вызова веб-службы? В главе 6 былопредставлено обходное решение с динамическим построением таблицы HTMLпри помощи объекта Sys.StringBuilder. Трюк отлично сработал. Но является литакое решение единственным? Должен существовать более изящный способ.

Макетные шаблоныВ конечном счете, динамическое построение строк является единственным спо-собом построения пользовательских интерфейсов в HTML с использованиемкоманд JavaScript. Проблема в том, что возможности построителей строк ограни-чены, и такое не назовешь простым и удобным. В фрагменте кода, приведенномв главе 6, не использовались стили, а решение ограничивалось объединением те-гов <tr> и <td>. А если вы захотите добавить стилевое оформление и выбиратьего на основании условий времени выполнения? Что, если в какой-то моментпотребуется изменить структуру полученной таблицы?

При поддержке аналогичных (и действительно реалистичных) схем логикаработы с построителями строк получается довольно сложной и запутанной.А «сложный и запутанный» также означает «подверженный ошибкам»; подоб-ные ситуации требуют досконального тестирования для всех возможных случаев

Page 272: Microsoft ASP.NET 2.0 AJAX

2 7 2 Глава 7. Привязка данных на стороне клиента

использования. Конечно, мы разработчики и тестирование — наш хлеб с маслом.И все же именно из-за того, что мы разработчики и программирование являетсянашей профессией, мы должны искать более качественные и эффективные спо-собы выполнения своей работы. На сцену выходят макетные шаблоны Atlas.

Макетные шаблоны представляют собой компоненты Atlas, которые помога-ют организовать <div> и другие теги HTML в периодическую структуру с заго-товками для данных. Макетные шаблоны обрабатываются специализированнымклиентским элементом Atlas — ListView. Для примера возьмем следующую раз-метку HTML:

<div id="searchResults"></div>

<div style="display: none;"><div id="LayoutTemplate">

<ul id="ItemTemplateParent"><li id="ItemTemplate">

<span>...</span><br /><span>...</span>,&nbsp;<span>...</span><hr />

</li></ul>

</div></div>

Верхний элемент <div> представляет точку, в которой будет вставляться ди-намически сгенерированная разметка, связанная с данными. Тег <div> с именемLayoutTemplate описывает структуру полученной разметки. Блок скрывается, по-тому что он служит лишь для передачи информации, а его содержимое разбира-ется и обрабатывается для получения реальной разметки. Элемент с именемItemTemplateParent обозначает блок разметки, содержащий повторяющиеся запи-си. Наконец, элемент с именем ItemTemplate представляет шаблон отдельных за-писей, каждая из которых связана с объектом данных.

Имена элементов, представляющих шаблоны макета, родительского элементаи записи данных, выбираются произвольно. Не стоит полагать, будто ключевыеслова LayoutTem plate, ItemTemplateParent и ItemTemplate имеют для Atlas какой-тоособый смысл. Однако при отображении шаблонов на элемент ListView именашаблонов назначаются специальным свойствам, обозначающим шаблоны маке-та, родителя и записи данных.

Макет, определяемый предшествующим фрагментом, обеспечивает представ-ление связанного источника данных в виде маркированного списка, при этом ка-ждая позиция списка превращается в две строки:

Company IDCompany Name, ContactName

Для преобразования шаблона в разметку, связанную с данными, потребуетсякод XML Script. Прежде всего необходимо создать компонент ListView для тега<div>, обозначающего заготовку для разметки (searchResults в приведенном при-мере). Но для начала стоит поближе познакомиться с программным интерфей-сом клиентского элемента Atlas ListView.

Page 273: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 7 3

Элемент ListViewЭлемент Sys.UI.Data.ListView принадлежит к числу элементов Atlas, связанных с дан-ными , и наследует от Sys.UI.Data.DataControl. Класс DataControl является родитель-ским для всех элементов Atlas, связанных с данными . Потомки DataControl под-держивают списковую привязку , а также привязку отдельных записей и средстваперемещения (навигации) . Свойства класса перечислены в табл. 7.4.

Таблица 7.4. Свойства элемента DataControl

Свойство Описание

canMoveNext

canMovePrevious

data

dataIndex

dataItem

length

Логическое свойство, указывающее, поддерживает ли элементперемещение в прямом направлении (по умолчанию True)

Логическое свойство, указывающее, поддерживает ли элементперемещение в обратном направлении (по умолчанию True)

Источник данных (чтение и запись). Значение представляетсобой коллекцию данных

Индекс элемента связанного источника данных, выбранногодля отображения (чтение и запись)

Текущая запись источника данных, если задано свойствоdataIndex (только чтение)

Количество записей данных в текущем связанном объектеисточника данных

Также базовый класс DataControl содержит четыре метода: addltem, deleteCurrent-Item, moveNext и movePrevious.

В табл. 7.5 перечислены специфические свойства элемента ListView.

Таблица 7.5. Свойства элемента ListView

Свойство ОписаниеalternatingItemCssClass

layoutTemplate

itemCssClass

itemTemplate

itemTemplateParentElementId

separatorCssClass

Имя стиля CSS, применяемого к каждой второйзаписи данных (чтение и запись)Шаблон HTML, определяющий макет всегопредставления (чтение и запись)

Имя стиля CSS, применяемого к каждой записиданных (чтение и запись)

Шаблон HTML, определяющий макет отдельныхзаписей данных (чтение и запись)

Идентификатор элемента HTML, который являетсяродителем по отношению к шаблону записи данных(чтение и запись). Как правило, используется дляопределения заголовка разметки

Имя стиля CSS, применяемого к разделителям,если таковые имеются (чтение и запись)

продолжение ■&

Page 274: Microsoft ASP.NET 2.0 AJAX

2 7 4 Глава 7. Привязка данных на стороне клиента

Таблица 7.5 (продолжение)

Свойство Описание

separatorTemplate Шаблон HTML, определяющий макет разделителя(чтение и запись)

emptyTemplate Шаблон HTML, определяющий макет всего списковогопредставления при отсутствии связанных данных(чтение и запись)

Шаблон Atlas является экземпляром класса Sys.UI.ITemplate. Для заполненияэлемента ListView используется код XML Script. Этот код должен установитьсоответствие между разметкой HTML и шаблонами, поддерживаемыми эле-ментом ListView.

Использование элемента ListViewДавайте начнем настройку элемента ListView с определения небольшого фрагмен-та разметки HTML, который должен быть связан с шаблонами (фактически этота же разметка, которую я приводил ранее, с другими идентификаторами и за-полненными элементами <span>).

<div id="searchResults"></div>

<div style="display: none;"><div id="search_LayoutTemplate">

<ul id="search_ItemTemplateParent"><li id="search_ItemTemplate">

<span id="search_ID"></span><br /><span id="search_Company"></span>,&nbsp;<span id="search_Contact"></span><hr />

</li></ul>

</div></div>

Тег searchResults указывает, в каком месте страницы должна быть вставленаразметка. С другой стороны, скрытый тег <div> содержит метаданные, а не реаль-ную разметку HTML для страницы. Скрытое содержимое этого блока описываетспособ построения разметки для списка.

Элемент с именем searchJtemTemplateParent определяет разметку, которуюдолжен сгенерировать элемент ListView перед тем, как приступать к переборусвязанных данных. Блок, помеченный как родительский шаблон, генерируетсятолько один раз. Он используется в Atlas практически так же, как вы исполь-зуете свойства HeaderTemplate и FooterTemplate в серверных шаблонных эле-ментах ASP.NET.

Элемент с именем searchJtemTemplate определяет шаблон HTML, которыйзаполняется данными и повторяется для каждой связанной записи данных.Шаблон может содержать произвольную комбинацию тегов HTML с уникаль-

Page 275: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 7 5

ным идентификатором. В конечном итоге приведенный ранее шаблон сгенериру-ет следующий код HTML:

<ul><li>

<span>...</span> <br/><span>...</span> Snbsp; <span>...</span><hr />

</li>

</ul>

Для получения этого блока разметки потребуется следующий код XML Script:<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components>

<listView id="searchResults"itemTemplateParentElementId=''search_itemTemplateParent''>

<layoutTemplate><template layoutElement="search_layoutTemplate" />

</layoutTemplate>

<itemTemplate><template layoutElement="search_itemTemplate">

<label id="search_ID"><bindings>

<bitiding dataPath="ID" property="text" /></bindings>

</label><label id="search_Company">

<bindings><binding dataPath="CompanyName" property="text" />

</bindings></label><label id="search_Contact">

<bindings><binding dataPath="ContactName" property="text" />

</bindings></label>

</template></itemTemplate>

</listView></components>

</page></script>

Компонент <NstView> связывается с тегом <div> searchResults и используетэлемент DOM с именем searchJtemTemplateParent в качестве родительского. Наэтом уровне можно задать классы CSS для оформления содержимого. Окон-чательный макет элемента ListView определяется блоком searchJayoutTemplateуправляющей страницы. Наконец, в шаблоне записи данных перечислены все

Page 276: Microsoft ASP.NET 2.0 AJAX

2 7 6 Глава 7. Привязка данных на стороне клиента

элементы DOM блока searchJtemTemplate управляющей страницы. Элементысвязываются с данными при помощи компонентов <label> и привязок Atlas:

<label id="search_ID"><bindings>

<binding dataPath="ID" property="text" /></bindings>

</label>

Например, тег <span> с именем search_ID ассоциируется с клиентским эле-ментом Label. Свойство text надписи связывается со свойством ID записи данных.

Как связать данные с клиентскими элементами? Есть два основных способа.Во-первых, можно написать обработчик клиентского события и вызвать методвеб-службы для загрузки данных. Когда это будет сделано, задается свойство dataэлемента, связанного с данными. Во-вторых, можно воспользоваться клиентскимкомпонентом-источником данных.

Программная привязка данныхЧтобы опробовать привязку данных, рассмотрим еще один пример. Он продол-жается с того места, на котором мы остановились в главе 6.

Допустим, имеется страница, подключенная к веб-службе Amazon. Страницаполучает коллекцию динамически созданных объектов JavaScript, которые необ-ходимо отобразить в табличном виде. Вот как выглядит код для создания спи-скового представления на базе таблицы HTML:

<div id="tableResults"></div>

<div style="display: none;"><div id="table_layoutTemplate">

<table cellpadding="2"><thead class="tableHeader"><tr>

<td><b>Book</b></td><td><b>Info</b></td>

</tr></thead><tbody id="table_itemTemplateParent"

class="tableContent"><tr id="table_itemTemplate" >

<td><img id="table_Cover" src="" alt="" />

</td><td>

<span id="table_ISBN"></span><br /><span id="table_Title"></span><br /><span id="table_Publisher"></span><br />

</td></tr>

</tbody></table>

</div></div>

Page 277: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 7 7

Таблица состоит из двух столбцов. В левом столбце выводится обложка кни-ги, а в правом — информация о ней (название, код ISBN и издатель). Необходи-мый код XML Script выглядит так:

<page xmlns:script="http://schemes.microsoft.com/xml-script/2005"><components>

<listView id="tableResults"itemTemplateParentElementId="table_itemTemplateParent">

<1ayoutTemplate><template layoutElement="table_layoutTemplate" />

</layoutTemplate><itemTemplate>

<template layoutElement="table_itemTemplate"><label id="tableResults_ISBN">

<bindings><binding dataPath="ISBN" property="text" />

</bindings></label><label id="tableResults_Title">

<bindings><binding dataPath="Title" property="text" />

</bindings></label><1 abel id="tableResults_Publisher">

<bindings><binding dataPath="Publisher" property="text" />

</bindings></label><image id="tableResults_Cover">

<bindings><binding dataPath="CoverPicture" property="imageURL" />

</bindings></image>

</template></itemTemplate>

</listView>

</components></page>

На странице находится клиентская кнопка, щелчок на которой приводит к вы-зову веб-службы. Обработчик щелчка на кнопке называется findBooks.

<script type="text/javascript">function findBooks(){

ShowProgress(true);var author = $("TextBoxl").value;IntroAtlas.AmazonPox.Find( {KeywordSearch:author},findBooksCompleted, findBooksTimeout, findBooksError);

}function findBooksCompleted(results, response, context){

var tableResults = $("tableResults");tableResults.control.set_data(results);ShowProgress(false);

}

Page 278: Microsoft ASP.NET 2.0 AJAX

2 7 8 Глава 7. Привязка данных на стороне клиента

function findBooksTimeout(results, context){

alert(results);ShowProgress(false);

}function findBooksError(results, response, context){

alert(results.getjnessageO);ShowProgress(false);

}function ShowProgress(busy){

if (busy){

$("ProgressBar").style.display = "";$("Buttonl").disabled = "disabled";

}else{

$("ProgressBar").style.display = "none";$("Buttonl").disabled = "";

}}

</script>

Ключевая операция выполняется в функции обратного вызова findBooks-Completed. При возврате управления веб-службой мы получаем данные и задаемсвойство data компонента ListView:

function findBooksCompleted(results){

var tableResults = $("tableResults");tableResults.control.set_data(results);

}

На рис. 7.1 показана страница в действии.

СОВЕТЗапустив страницу, вы заметите, что получение данных сопровождается анимацией.Чтобы добиться этого эффекта, достаточно определить пользовательский класс CSS сосвойством background-image, которому назначен анимированный GIF-файл. Далее ос-тается лишь присоединить стиль к элементу на странице и отображать/скрывать его помере надобности.

Клиентские компоненты источников данныхКак и в случае с серверными элементами, для заполнения клиентских элементовAtlas, связанных с данными, могут использоваться специальные компоненты, назы-ваемые источниками данных. Связь между клиентскими элементами и источника-ми данных устанавливается на декларативном уровне в коде XML Script посредст-

Page 279: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 7 9

вом элемента <binding>. При использовании источников данных функция привязкистановится полностью декларативной и совершенно не требует кода JavaScript.

Рис. 7.1. Привязка данных от веб-службы Amazon

Класс Sys.Data.DataSourceКомпоненты-источники данных Atlas являются экземплярами класса Sys.Data.DataSource. В отличие от классической модели ASP.NET с несколькими различ-ными компонентами источников данных (ObjectDataSource, SqIDataSource и т. д.),в Atlas существует только один объект источника данных верхнего уровня — классDataSource, делегирующий задачи доступа к данным пользовательским службамданных. Иерархия показана на рис. 7.2.

Программный интерфейс класса DataSource определяется в табл. 7.6.Источник данных инициализируется либо явно заданными исходными данны-

ми, либо настраивается на автоматическую загрузку данных (autoLoad). Источникданных хранит данные в своем внутреннем представлении в виде объекта Sys.Data.DataTable. Впрочем, массивы и коллекции объектов также допустимы; после при-сваивания компоненту они загружаются в клиентский объект DataTable.

Page 280: Microsoft ASP.NET 2.0 AJAX

2 8 0 Глава 7. Привязка данных на стороне клиента

loadi

Sys.Data DataSource

Клиент Atlas

ASP.NETServer

Методс пометкой ■*

SELECT

Внутренний ""■GetDataвызов

Для операций загрузкивызывается GetData

Для операций записивызывается SaveData

YourDataService.asmx

IMicrosoftWeb.Services.DataService

1System.Web.Services.Webservice

Метод+ с пометкой

DELETE,UPDATE,INSERT

SaveData - Внутреннийвызов

Рис. 7.2. Источники данных и службы данных в Atlas

Таблица 7.6. Члены класса DataSource

Член класса Описание

autoLoad

data

dataAvailable

initialData

isDirtyAndReady

isReady

load

loadMethod

parameters

rowCount

Логическое свойство, указывающее, что источник данных долженначать загрузку данных сразу же после того, как будет загруженв странице (по умолчанию false)

Данные, хранящиеся в источнике (чтение и запись). Допустимыетипы — массивы и объекты Sys.Data.DataTable

Событие, которое происходит при наличии в источнике данных,готовых к отображению

Строка JSON, предназначенная для чтения и записи исходногосодержимого источника данных. Не задается при истинномсвойстве autoLoad

Логическое свойство, указывающее, что источник данных готовк пакетному обновлению — то есть данные доступны, и имеютсянеобработанные изменения

Логическое свойство, указывающее, что источник данных готов к выводу

Метод для загрузки данных в компонент. Вызывает метод службыданных, помеченный как метод SELECT. Если один атрибутсовместно используется несколькими методами, для определениянужного метода используется свойство loadMethod

Имя метода службы данных, вызываемого для получения данных.Свойство задается при наличии у службы нескольких методов SELECT

Массив параметров, передаваемых вызываемому методу службы данных

Количество записей в источнике данных (только чтение)

Page 281: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 8 1

Член класса ОписаниеserviceURL URL используемой службы данных (чтение и запись)

save Метод для сохранения необработанных изменений в службе данных.Реализует своего рода режим пакетного обновления с активнойобработкой данных, содержащих незавершенные изменения — такие, как операции удаления, обновления и вставки

Механика работы источников данныхКласс Sys.Data.DataSouce представляет собой клиентский компонент, способныйподключаться к домашнему серверу и загружать обновленные данные для кли-ентских операций. Подключение производится через механизм веб-служб, опи-санный в главе 6.

«Партнером» клиентского источника данных на стороне сервера являетсякомпонент службы данных. Служба данных представляет собой серверныйкласс, производный от DataService — класса, определенного в пространстве именMicrosoft.Web.Services. Класс DataService в конечном счете наследует от System.Web.Services. WebService; фактически он является особой разновидностью веб-службы ASP.NET (см. рис. 7.2).

Чтобы организовать привязку данных Atlas через источник, вы создаете соб-ственную службу данных и открываете доступ к ней как к домашней веб-службе(вскоре я объясню более подробно). URL службы данных передается источникуданных в свойстве serviceURL. Настройка источника данных определяется сле-дующим фрагментом XML Script:

<dataSource id="dataSourcel" serviceURL="MyDataSource.asmx" />

Атрибут autoLoad обеспечивает автоматическую загрузку данных при загруз-ке страницы. Если он не используется, загрузка данных осуществляется методомload источника данных. Следующий фрагмент кода функционально эквивален-тен заданию истинного свойства autoLoad:

<page xmlns:script="http://schemes.microsoft.com/xml-script/2005"><components>

<application><load>

<invokeMethod target="dataSourcel" method="load" /></load>

</application><dataSource id="dataSourcel" serviceURL="MyDataSource.asmx" />

</components></page>

Для дополнительного контроля за ходом операции можно воспользоватьсякодом JavaScript:

<script type="text/javascript">function findCustomers(dataSource){

Page 282: Microsoft ASP.NET 2.0 AJAX

2 8 2 Глава 7. Привязка данных на стороне клиента

ShowProgress(true);

$object("dataSource1").load();

}

</script>

На рис. 7.3 показана страница в действии.

Рис. 7.3. Управление загрузкой данных в Atlas

В некоторых случаях требуется организовать оповещение о появлении дос-тупных данных с целью обновления некоторых фрагментов пользовательскогоинтерфейса. Для этого перехватывается событие dataAvailable:

<dataSource id="dataSourcel" serviceURL="MyDataSource.asmx"dataAvailable="DataIsHere" />

Объект источника данных передается обработчику события в аргументе:function DatalsHere(dataSource){

ShowProgress(false);alert(dataSource.get_rowCount() + " rows ready. Click to display.");

}

Событие dataAvailable задействовано в обратном вызове по завершении мето-да при обращениях к веб-службам.

Метод load источника данных организует вызов веб-службы, направленныйк конечной точке службы данных — свойству serviceURL. При обращении будетвызван метод GetData службы. В соответствии с архитектурными требованиямикласс службы данных должен быть производным от серверного класса DataService,который предоставляет всего лишь два метода: GetData и SaveData. Соответст-венно, эти методы присутствуют во всех пользовательских службах данных.

Внутренняя реализация конструктора DateService использует механизм рефлек-сии для получения и сохранения информации о методах, помеченных атрибутомDataObjectMethod. Значения атрибута - Select, Update, Delete и Insert - объедине-ны в перечисляемый тип DataObjectMethodType. Таким образом, каждый метод

Page 283: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 8 3

службы данных предоставляет информацию о своей роли. Метод GetData при-надлежит к числу так называемых «фасадных методов»: он просто выбирает ме-тод, помеченный атрибутом Select, и вызывает его. Что, если атрибут назначеннескольким методам службы данных? В этом случае GetData выбирает первыйиз указанных методов, если только источник данных не дает явного указания навызываемый метод. Атрибут loadMethod сообщает, какой из методов (Select) дол-жен быть вызван для источника данных. Если loadMethod ссылается на метод, непомеченный атрибутом Select, происходит исключение.

Аналогичным образом, метод save источника данных выбирает методы, поме-ченные атрибутами Delete, Update и Insert, и выполняет их в указанном порядке.Метод save инициирует своего рода пакетную операцию обновления. Он извле-кает из своих данных записи, содержащие необработанные изменения, и после-довательно перебирает их. Следующий псевдокод показывает, как реализованаэта процедура:

foreach (object row in changeList.Deleted){

DataService.InvokeMethod(DataObjectMethodType.Delete, row);}foreach (object row in changeList.Updated){

DataService.InvokeMethod(DataObjectMethodType.Update, row);}foreach (object row in changeList.Inserted){

DataService.InvokeMethod(DataObjectMethodType.Insert, row);}

Определять несколько методов с атрибутами Delete, Update или Insert в служ-бе данных запрещается. При нарушении этого правила происходит исключение.

Создание пользовательской службы данныхПользовательская служба данных представляет собой класс, производный от Data-Service. Класс содержит несколько открытых методов, помеченных специальныматрибутом DataObjectMethod. Как упоминалось ранее, этот атрибут предназнача-ется для пометки методов, выполняющих операции Select, Insert, Update и Delete.

ПРИМЕЧАНИЕАтрибут DataObjectMethod не является специфическим для Atlas. Он определяетсяв пространстве имен System.ComponentModel сборки System. Этот атрибут, изначальнопоявившийся в ASP.NET 2.0 для описания объектов данных в визуальных средах вродеMicrosoft Visual Studio 2005, идентифицирует тип метода. В Atlas атрибут используетсядля той же цели, но применяется к другому объекту — компоненту источника данных.

Доступ к классу службы данных предоставляется через открытую конечнуюточку .asmx. Пример класса службы данных:

namespace IntroAtlas.WebServices{

[WebService(Namespace = "http://introatlas.book/")][WebServiceBinding(ConformsTo = WsiProfiles.BasicProfilel_l)]

Page 284: Microsoft ASP.NET 2.0 AJAX

2 8 4 Глава 7. Привязка данных на стороне клиента

public class MyDataSource : DataService{

[WebMethod][DataObjectMethod(DataObjectMethodType.Select);

public CustomerCollection LookupAllCustomers(){

return CustomerManager.LoadAl 1 0 ;}[WebMethod;[DataObjectMethod(DataObjectMethodType.Select) [

public CustomerCollection CustomersInSouthAmericaO{

return CustomerManager.LoadFromSouthAmerica();}

public CustomerCollection LookupCustomers(string query){

return CustomerManager.LoadBylnitial(query);}

[WebMethod;[DataObjectMethod(DataObjectMethodType.Update);public Customer UpdateCustomer(Customer cust){

return CustomerManager.Save(cust);}

}}

Класс связывается с конечной точкой .asmx следующим образом:

<%& WebService Language="C#" CodeBehind="-/App_Code/MyDataSource.cs"Class="IntroAtlas.WebServices.MyDataSource" %>

Давайте проанализируем исходный код класса более подробно. Класс содер-жит два метода Select и один метод Update. Это означает, что служба не можетиспользоваться с элементом данных, поддерживающим удаление и вставку.

Атрибут DataObjectMethod независим от атрибута WebMethod. Атрибут Web-Method не является строго обязательным для методов источника данных. Тем неменее, как вам, вероятно, уже известно, методы без атрибута WebMethod не могутвызываться в удаленном режиме извне (за пределами механизма источниковданных Atlas), потому что такой метод даже не будет объявлен в качестве вызы-ваемого метода веб-службы.

ПРИМЕЧАНИЕС учетом сказанного метод LookupCustomers, приведенный в коде примера, не являетсяметодом Select с точки зрения клиента, потому что он не обладает атрибутом Data-ObjectMethod. Более того, клиент даже не будет знать о существовании метода Lookup-Customers, так как из-за отсутствия атрибута WebMethod ASP.NET не предоставитдоступ к методу через Web. Таким образом, он больше напоминает вспомогательныйметод для класса MyDataSource (а может, разработчик просто забыл пометить методнужными атрибутами!)

Page 285: Microsoft ASP.NET 2.0 AJAX

Привязка данных к элементам 2 8 5

Какую информацию должны возвращать методы служб данных?Как упоминалось ранее, клиентский источник данных хранит свои данные

в клиентском объекте DataTable — клиентском «партнере» класса ADO.NET Data-Table. Это означает, что методы служб данных без каких-либо проблем принима-ют и возвращают объекты ADO.NET — такие, как DataTable, DataSet, DataViewи DataRow. Кроме того, источники данных Atlas поддерживают массивы и кол-лекции. А это означает, что службы данных могут работать с пользовательскимиобъектами и их коллекциями, как в предыдущем примере с классами Customerи Customer-Collection.

Однако обратите внимание, что источник данных преобразует объекты Cus-tomer и коллекции в клиентский объект DataTable. Пользовательский объектдолжен явно указать, какие из его свойств должны загружаться в столбцы табли-цы. Только свойства, помеченные атрибутом DataObjectField, загружаются и ста-новятся доступными через интерфейс источника данных. Иначе говоря, еслисвойство пользовательского объекта, используемого для пересылки данных ис-точнику данных и обратно, не обладает атрибутом DataObjectField, прямая при-вязка результатов к ListView невозможна. Следующий класс используется дляпредставления клиента; обратите внимание на пометку свойства CompanyNameатрибутом DataObjectField, чтобы значение свойства могло использоваться дляпрямой привязки на стороне клиента:

public class Customer{

// Приватные поляprivate string jcompanyname;

[DataObjectField(false);public string CompanyName{

get { return jcompanyname; }set { jcompanyname = value; }

}

}

Разумно предположить, что классы представления сущностей (такие, какCustomer) будут определяться на уровне бизнес-логики вашего приложения. До-бавленный атрибут DataObjectField будет проигнорирован всеми верхними уров-нями представления, за исключением Atlas. Атрибут DataObjectField может полу-чать до четырех параметров:

public DataObjectFieldAttribute(bool primaryKey, bool isldentity, bool isNullable, int length)

Как минимум необходимо указать, является ли свойство первичным ключом.По умолчанию считается, что свойство не представляет идентифицирующихстолбцов и не допускает значения null.

Page 286: Microsoft ASP.NET 2.0 AJAX

2 8 6 Глава 7. Привязка данных на стороне клиента

ПРИМЕЧАНИЕЭлемент ListView воспроизводит данные «порциями» по пять записей, чтобы браузерне переставал реагировать на действия пользователя при большом объеме данных.Этот режим называется пошаговым воспроизведением.

Расширенные функцииДо настоящего момента мы рассматривали основные возможности Atlas по кли-ентской привязке данных. Однако тема далеко не исчерпана; существует ещенемало элементов и функций, с которыми необходимо познакомиться. Как выубедитесь в оставшейся части главы, Atlas предоставляет поддержку странично-го вывода данных, сортировки, двусторонней привязки данных и специализиро-ванных представлений.

Построение расширенных списковыхпредставленийКак правило, при представлении данных в веб-приложениях используются двеосновных модели: списковая и детализированная. На классической платформеASP.NET эти две модели представлены двумя исключительно популярнымиэлементами: GridView и DetailsView. Библиотека Microsoft AJAX не предоставляетстоль широкого выбора элементов, как сборка ASP.NET system.web, однако в нейимеется все необходимое для эффективного построения списковых и детализи-рованных представлений. К настоящему моменту вы уже знакомы с основнымипринципами работы элемента ListView и знаете, как связать его с данными напрограммном или декларативном уровне. Что дальше?

Процесс привязки данных к элементу можно сделать более эффективными функциональным, наделив его некоторыми дополнительными возможностями.Давайте рассмотрим некоторые из них.

Отправка исходных данныхПосле того как страница будет настроена для работы с данными с использова-нием источника данных, в ней можно включить необязательный режим авто-загрузки. В этом случае разработчик избавляется от хлопот по заполнению ис-точника данных и связанных элементов. Впрочем, не все так просто — взглянитена рис. 7.4.

Если источник данных используется в режиме автозагрузки, серверу направ-ляются два запроса: первый (управляемый пользователем) загружает страницу,а второй (управляемый компонентом источника данных) принимает ее дан-ные. Если загружаемые автоматически данные не зависят от параметров вре-мени выполнения, их можно внедрить в разметку страницы. В этом случаеданные для инициализации источника поступают с первым запросом, и необ-ходимость в дополнительном запросе для инициализации пользовательского ин-терфейса отпадает.

Page 287: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 8 7

БраузерБраузерЗагрузка страницы по запросу

пользователяЗагрузка страницы по запросу

пользователя

Браузер Начинается построение страницыИсточник данных размещаетвторой запрос для загрузки

своих данных (autoLoad = true)

БраузерСодержимое элемента ListView

на странице полностьюсформировано

Рис. 7.4. Для загрузки страницы и данных необходимы два запроса к серверу

Инициализационные данные для источника данных представляют собой тек-стовую строку, представляющую JSON-сериализованный объект. Следующийфрагмент кода демонстрирует передачу инициализационных данных компонен-ту-источнику:

<script type="text/xml-script"> <page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<components><dataSource>

<initialData><![CDATA[ ... ]]>

</initialData><bindings>

<binding dataContext="dataSourcel" dataPath="data"property="data" direction="Out" />

</bindings></dataSource>

</components></page></script>

Вы определяете дополнительный компонент <dataSource> и заполняете егоэлемент <initialData> JSON-представлением объекта, связываемого через Java-Script — например, коллекции. Вновь созданный компонент <dataSource> включаетпривязку к заполняемому компоненту-источнику данных. Атрибут direction="Out"означает, что источник данных, владеющий привязкой, является источником(а не приемником) при передаче данных. Во всех остальных привязках, рассмат-ривавшихся ранее, объект, указанный в атрибуте dataContext, был владельцемданных, передававшихся объекту-владельцу привязки. С инициализационны-ми данными все происходит в обратном направлении — собственно, именно этои означает атрибут direction компонента <binding>.

Page 288: Microsoft ASP.NET 2.0 AJAX

2 8 8 Глава 7. Привязка данных на стороне клиента

Как выглядит JSON-сериализованный объект? В следующем фрагменте пред-ставлен объект Sys.Data.DataTable с тремя столбцами и одной строкой:

new Sys.Data.DataTable([new Sys.Data.DataColumn("CompanyName",String,nul 1,false,false),new Sys.Data.DataColumn("ContactName",String,nul 1,false,false),new Sys.Data.DataColumn("Country",String,null,false,false)

],[{"CompanyName":"Alfreds Futterkiste","ContactName":"Maria Anders","Country":"Germany"},

}~_

Конечно, вводить этот текст вручную было бы весьма противно, особенноесли источник данных содержит несколько записей. Также присутствует и дру-гой, гораздо более важный фактор — возможно, вы захотите управлять предо-ставляемыми данными на программном уровне. На помощь приходит новый сер-верный элемент Atlas Initial Data:

<atlas:InitialData runat="server" id="InitialDatal"servicePath="~/samples/ch07/complex/MyDataSource.asmx"ClientDataSourceID="dataSourcel">

</atlas:InitialData>

При настройке элемента InitialData необходимо указать действительный вир-туальный путь к службе данных.

Элемент InitialData вызывает метод GetData указанной службы данных и гене-рирует приведенный ранее блок XML Script, вместе с привязками и JSON-сериа-лизованными данными. Независимо от того, возвращает ли метод Select службыданных пользовательскую коллекцию или объект ADO.NET DataTable, элементInitialData сериализует такие данные в JSON и обеспечивает их загрузку в кли-ентском элементе, связанном с данными.

ПРИМЕЧАНИЕПосле инициализации клиентский компонент DataSource вызывает метод load, еслисвойство autoLoad равно true, или при наличии инициализационных данных. Внутрен-няя реализация load сначала проверяет инициализационные данные. Если они заданы,метод загружает данные и возвращает управление. В противном случае выдается следую-щий запрос на прием данных. Обратите внимание: после приема данных содержимоесвойства initialData сбрасывается. Данные, присвоенные initialData на программномуровне, будут проигнорированы, если источник уже связан с данными.

Сортировка данных на стороне клиентаВ большинстве случаев список данных наполовину утрачивает свою полезность,если его нельзя сортировать по разным полям и направлениям. В классической мо-дели ASP.NET элементы DataGrid и GridView обладают встроенной поддержкой

Page 289: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 8 9

сортировки. Пользователь щелкает на гиперссылках, страница производит воз-врат данных, обновляет представление данных и перерисовывает изображе-ние. Сортировка сетки приводит к выполнению двух высокозатратных операций.Во-первых, страница возвращает данные и полностью обновляется. Во-вторых,источник данных сетки сортируется, а сортировка не принадлежит к числу про-стых операций.

У первой проблемы есть изящное решение: сетка вставляется в элемент Up-datePanel. В результате вам не придется осваивать новую модель программирова-ния, а последствия от возврата данных для отображаемой страницы существенноснижаются. Что делать со второй проблемой — вычислительной сложностьюсортировки?

Честно говоря, вряд ли вам удастся сделать что-нибудь для заметного ускоре-ния операций сортировки — не считая кэширования заранее отсортированныхтаблиц данных. Если вам потребуются расширенные средства сортировки, рабо-тающие по нескольким полям и в разных направлениях с большими таблицамиданных, самым быстрым средством сортировки в конечном счете оказываетсясервер баз данных. Однако обращения к серверу за сортировкой, даже без учетазатрат на возвраты данных, создадут немалую нагрузку для канала связи.

Как насчет сортировки на стороне клиента? Прежде, до появления Atlas,такое решение не было невозможным, но возможность скорее оставалась теоре-тической. Прикладная среда Atlas и язык XML Script позволяют легко справить-ся с этой задачей.

Важнейшее изменение, которое необходимо внести в ListView для поддержкисортировки на стороне клиента, — это его связывание с объектом DataView вместообъекта DataSource. В свою очередь, DataView получает информацию от источни-ка данных:

<dataSource id="dataSourcel" servicellRL="MyDataSource.asmx" /><listView id="tableResults"

itemTemplateParentElemeriti d="table_itemTemplateParent"><bindings>

<bitiding dataContext="view" dataPath="filteredData" property="data" /></bindings>

</listView><dataView id="view">

<bindings><bitiding dataContext="dataSourcel" dataPath="data" property="data" />

</bindings></dataView>

Модель в целом напоминает решение, использовавшееся для создания сорти-руемых сеток в классических приложениях ASP.NET. Элемент сетки связываетсяс объектом ADO.NET DataView, построенным на базе объекта ADO.NET DataTable.В ASP.NET и Atlas объект представления не хранит сами данные и ограничива-ется предоставлением отфильтрованного или отсортированного представлениясвязанных данных. В табл. 7.7 перечислены члены класса Atlas DataView.

Как видно из таблицы, объект DataView также обладает широкими возможно-стями для страничного вывода содержимого клиентского источника данных.Вскоре мы вернемся к теме страничного вывода.

Page 290: Microsoft ASP.NET 2.0 AJAX

2 9 0 Глава 7. Привязка данных на стороне клиента

Таблица 7.7. Члены класса Sys. Data. Data View

Член класса Описаниеdata Данные, используемые для построения представления (чтение и запись)

filteredData Данные текущего представления. Представление может отличатьсяот исходных данных из-за сортировки или фильтров

filters Коллекция условий, ограничивающих состав записей текущегопредставления

hasNextPage Логический признак, определяющий возможность переходак следующей странице

hasPreviousPage Логический признак, определяющий возможность переходак предыдущей странице

length Количество записей в текущем представлении

pageCount Количество страниц в текущем представлении

pageIndex Индекс страницы, выбранной в текущем представлении

pageSize Размер страницы (чтение и запись)

sort Метод сортировки представления

sortColumn Имя столбца, по которому выполняется сортировка (чтение и запись)

sortDirection Направление сортировки: по возрастанию (Ascending) или по убыванию(Descending) (чтение и запись)

Чтобы завершить пример , в котором пользователи могут сортировать наборданных на стороне клиента, необходимо включить в пользовательский интерфейсгиперссылки :

<table eel 1padding="2"><thead class="tableHeader">

<tr><td><t»

<a href="javascript:;" id="sortByCompany">Customer</a></t»</td><td><t»

<a href="javascript:;" id="sortByContact">Contact</a></t»</td>

</tr></thead>

</table>

Если списковое представление оформляется в виде таблицы , заголовки столб-цов можно заключить в тег <а>. Затем в X M L Script эти гиперссылки связыва-ются с новым аспектом поведения — sortBehavior:

<control id="sortByCompany">

<behaviors>

<sortBehavior dataView="view" sortColumn="CompanyName" />

</behaviors>

Page 291: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 9 1

</control><control id="sortByContact">

<behaviors><sortBehavior dataView="view" sortColumn="ContactName" />

</behaviors></control>

Разумеется, столбцы сортировки должны соответствовать столбцам связан-ного источника данных. Сортировка выполняется исключительно на сторонеклиента без возвратов данных — как полных, так и ограниченных возвратовAtlas. Аспект поведения сортировки достаточно сообразителен, чтобы автомати-чески изменить направление сортировки при повторном щелчке на сортируе-мом столбце. Сортировка выполняется по алфавиту или по числовым значениям,в зависимости от типа столбца данных.

ПРИМЕЧАНИЕСортировка, производимая на стороне клиента, безвозвратно теряется при возвратеданных страницей, а содержимое элемента строится заново. Также следует учитывать,что клиентская сортировка реализована на JavaScript. Поэтому не ожидайте, что онабудет быстро работать, и применяйте ее только при небольшом количестве записей(на мой взгляд, не более 20).

Страничный вывод данных на стороне клиентаКак упоминалось ранее, компонент DataView поддерживает страничный выводданных. Но как управлять выбором отображаемой страницы и настроить пользо-вательский интерфейс для перемещения между страничными блоками данных?Для этого на странице размещается новый компонент DataNavigator, которыйсвязывается с представлением. У компонента DataView должен быть явно заданразмер страницы.

<dataNavigator id="dataNavigatorl" dataView="view" /><dataView id="view" pageSize="10">

<bindings><bitiding dataContext="dataSourcel" dataPath="data" property="data" />

</bindings></dataView>

Компонент DataNavigator связывается с элементом страницы, представляющимпанель перемещения. Пример:

<div id="dataNavigatorl"><input type="button" id="firstPageButton" value="&lt;&lt;" /><input type="button" id="previousPageButton" value="&lt;" /><span id="pageIndexLabel"></span>out of<span id="pageCountLabel"></span><input type="button" id="nextPageButton" value="&gt;" /><input type="button" id="lastPageButton" value="&gt;&gt;" />

</div>

Page 292: Microsoft ASP.NET 2.0 AJAX

2 9 2 Глава 7. Привязка данных на стороне клиента

Типичная панель перемещения содержит четыре кнопки: переход к пер-вой, предыдущей, следующей и последней странице. Каждая кнопка переходадолжна быть ассоциирована с компонентом Atlas и связана со свойствами объек-та DataView:

<button id="previousPageButton"parent="dataNavigatorl" command="previousPage">

<bindings><bitiding property="enabled" dataPath="hasPreviousPage" />

</bindings></button><button id="nextPageButton"

parent="dataNavigatorl" command="nextPage"><bindings>

<bitiding property="enabled" dataPath="hasNextPage" /></bindings>

</button><button id="firstPageButton"

parent="dataNavigatorl" command="firstPage"><bindings>

<binding property="enabled" dataPath="hasPreviousPage"></bindings>

</button><button id="lastPageButton"

parent="dataNavigatorl" command="lastPage"><bindings>

<binding property="enabled" dataPath="hasNextPage" /></bindings>

</button>

У кнопок, предназначенных для перехода вперед и назад, свойство enabledможет связываться со свойствами hasNextPage и hasPreviousPage представленияданных. В этом случае разработчику не придется беспокоиться об установлениии снятии блокировки кнопок при переходе между страницами.

Атрибут parent играет ключевую роль: благодаря ему родительский компонент(в данном случае DataNavigator) получает события, поступающие от дочернихэлементов. В результате DataNavigator перехватывает щелчки на кнопках и полу-чает информацию, связанную с атрибутом command. Во внутренней реализацииDataNavigator используется команда выбора switch с соответствующим назначениеминдекса страничного блока. DataNavigator распознает четыре команды: previous-Page, nextPage, firstPage и lastPage. На рис. 7.5 показано, как выглядит страницаиз нашего примера в действии.

В приведенном примере реализован механизм перехода к следующей/преды-дущей странице. Также возможен вариант с прямым переходом, при котором длякаждого страничного блока создается отдельная кнопка или гиперссылка. В этомслучае кнопка ассоциируется с командой page, чтобы панель перемещения рас-познала команду, а индекс запрашиваемой страницы указывается в атрибутеargument:

<button id="pageButton3" parent="dataNavigatorl"command="page" argument="3" />

Page 293: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 9 3

Рис. 7.5. Страница с сортировкой и страничным выводом информации на стороне клиента

В схеме перехода к следующей/предыдущей странице пользователю будетполезно знать, сколько страничных блоков входит в текущий набор данных, а так-же индекс текущего страничного блока. Для достижения желаемого результата,показанного на рис. 7.5, используются два тега <span>: для индекса страничногоблока и для общего количества блоков.

<t»<span id="pagelndex"></span></t»■4nbsp;&nbsp; out of &nbsp;&nbsp;<b><span id="pageCount"></span></b>

Также потребуется следующий фрагмент XML Script:<label id="pagelndex">

<bindings><bitiding dataContext="view" dataPath="pageIndex" property="text"

transform="Add" /></bindings>

</label><label id="pageCount">

<bindings><binding dataContext="view" dataPath="pageCount" property="text" />

</bindings></label>

Page 294: Microsoft ASP.NET 2.0 AJAX

2 9 4 Глава 7. Привязка данных на стороне клиента

Трюк с преобразователем Add помогает решить проблему с индексированиемстраничных блоков, начинающимся с 0, и вывести более реалистичный номер те-кущей страницы.

Создание детализированных представленийСетка не всегда является лучшим способом отображения данных. Нередко поль-зователю бывает удобнее просматривать данные одной записи на специальнойформе. В классических приложениях ASP.NET существует два элемента, значи-тельно упрощающих эту задачу: DetailsView и FormView. Первый предоставляетфиксированный, табличный пользовательский интерфейс с двумя столбцами:для названий полей и для их значений. Пользовательский интерфейс элементаможет быть дополнен кнопками перехода и выполнения базовых операций — таких, как удаление и обновление текущей записи или создание новой записи.Элемент FormView с точки зрения функциональности служит той же цели, чтои DetailsView, но он обладает полноценными шаблонными элементами, а все эле-менты и составляющие пользовательского интерфейса должны определятьсявручную — так достигается гораздо большая гибкость, но за счет существенногоувеличения объема работы по программированию.

В Atlas для создания детализированных представлений используется клиент-ский элемент ItemView — парный по отношению к элементу ListView, описанномуранее в этой главе. Оба элемента обладают общим базовым классом (DataControl)и могут заполняться как на программном уровне через свойство data, так и надекларативном уровне через компоненты-источники данных.

Элемент ItemViewЭлемент ItemView обладает тремя свойствами. Два из них — itemTemplate и empty-Template — представляют собой шаблоны. Эти свойства играют ту же роль, каки для элемента ListView. Свойство itemTemplate содержит блок разметки HTML,используемый для построения детализированного представления записи данных.Свойство emptyTemplate определяет разметку, которая отображается при отсут-ствии данных, связанных с элементом. Последнее свойство элемента, CssClass,определяет стиль CSS, используемый для изменения внешнего вида элемента.

Свойство itemTemplate позволяет взять под полный контроль пользователь-ский интерфейс, отображаемый для каждой связанной записи. Привязки исполь-зуются для присоединения данных к элементам пользовательского интерфейса — таким, как текстовые поля и надписи. Разработчик также должен предоставитьпанель перемещения и другие кнопки, необходимые для редактирования, встав-ки и удаления записей данных.

Построение детализированного представленияПервым шагом в построении детализированного представления должно статьопределение позиции основной страницы, в которой будет вставляться динами-чески сгенерированная разметка:

<div id="detailsView"></div>

Page 295: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 9 5

Затем добавляется скрытый блок <div> для определения шаблона записиданных. Следующая разметка строит табличное представление записи данных,практически полностью идентичное тому, которое обеспечивается сервернымэлементом DetailsView. Каждое связанное поле представлено в таблице отдельнойстрокой: один столбец для имени поля и один столбец для чтения и редактиро-вания значения:

<div style="display: none"><div id="details_Template">

<table cellpadding="2"><thead class="tableHeader"><tr>

<td><t»Fields</t»</td><td><t»&nbsp;</t»</td>

</tr></thead><tbody class="tableContent"><tr>

<td><b>Customer ID</b></td><td><asp:textbox runat="server"

</tr><tr>

<td><b>Company Name</b></td><td><asp:textbox runat="server"

</tr><tr>

<td><b>Contact</b></td><td><asp:textbox runat="server"

</tr><tr>

<td><b>Country</b></td><td><asp:textbox runat="server"

</tr></tbody>

</table>

</div></div>

Шаблон позволяет просматривать и редактировать четыре поля связаннойзаписи данных: код клиента, название компании, имя контактного лица и страну.Реализация необходимого клиентского поведения обеспечивается следующимкодом XML Script:

<dataSource id="dataSourcel" serviceURL="MyDataSource.asmx" /><itemView id="detailsView">

<bindings><bitiding dataContext="dataSourcel" dataPath="data" property="data" />

</bindings><itemTemplate>

<template 1ayoutElement="detai1s_Template"><textBox id="details_CustomerID">

<bindings><binding dataPath="ID" property="text"

direction="InOut" /></bindings>

id="details_CustomerID" /></td>

id="details_CompanyNanie" /></td>

id="details_Contact" /></td>

id="details_Country" /></td>

Page 296: Microsoft ASP.NET 2.0 AJAX

2 9 6 Глава 7. Привязка данных на стороне клиента

</textBox><textBox id="details_CompanyName">

<bindings><binding dataPath="CompanyName" property="text"

direction^'InOut" /></bindings>

</textBox><textBox id="details_Contact">

<bindings><binding dataPath="ContactName" property="text"

direction^'InOut" /></bindings>

</textBox><textBox id="details_Country">

<bindings><binding dataPath="Country" property="text"

direction^'InOut" /></bindings>

</textBox></template>

</itemTemplate></itemView>

Шаблон, корневым элементом DOM которого является details_Template, со-держит текстовые поля, связанные с полями источника данных. В целом кодпочти не отличается от того, который использовался ранее для элемента ListView,не считая заданного значения атрибута direction привязки. Вскоре мы вернемсяк этому обстоятельству при обсуждении двусторонних привязок. На рис. 7.6показано, как выглядит представление, созданное нами к настоящему моменту.

Рис. 7.6. Пример детализированного представления связанных данных

Page 297: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 9 7

Объект ItemView связывается со всем источником данных, возвращеннымслужбой; однако на экране отображается содержимое только одной записи. Сле-довательно, мы должны добавить кнопки, чтобы дать возможность пользовате-лям перебирать связанные записи — уже загруженные на сторону клиента.

Структура панели перемещения зависит только от вас. Как минимум на нейжелательно разместить пару кнопок для перехода к предыдущей и следующейзаписи данных, а также кнопку для сохранения необработанных изменений. При-мер возможной структуры панели:

<div id="itemNavigator"><input type="button" id="previousButton" value="&lt;" />■inbsp;Snbsp;<b><span id="itemlndex"></span></b>■4nbsp;&nbsp;out of&nbsp;&nbsp;<b><span id="itemCount"x/span></b>&nbsp;Snbsp;<input type="button" id="nextButton" value="&gt;" /><hr /><input type="button" id="saveButton" value="Save" />

</div>

На панели перемещения также находится пара надписей для вывода индексатекущей записи и общего количества связанных записей. Как обычно, эта раз-метка практически бесполезна без дополняющего кода XML Script. Вот как вы-глядит сценарный код привязки надписей:

<label id="itemlndex"><bindings>

<binding dataContext="detailsView" dataPath="dataIndex"property="text" transform="Add" />

</bindings></label><label id="itemCount">

<bindings><binding dataContext="detailsView" dataPath="length"

property="text" /></bindings>

</label>

Согласно CTP (Community Technology Preview) за июль 2006 года, элементыданных не поддерживают методы перехода к первой или последней связаннойзаписи данных. Впрочем, разработчик может реализовать эту возможность припомощи обработчиков событий и кода JavaScript. Для операций, поддерживае-мых элементами данных, можно воспользоваться простой привязкой данных, какпоказано в следующем примере:

<button id="previousButton"><bindings>

<binding dataContext="detai1sView" dataPath="canMovePrevious"property="enabled" />

</bindings><click>

<invokeMethod target="detailsView" method="movePrevious" /></click>

</button>

Page 298: Microsoft ASP.NET 2.0 AJAX

2 9 8 Глава 7. Привязка данных на стороне клиента

<button id="nextButton"><bindings>

<bitiding dataContext="detailsView" dataPath="canMoveNext"property="enabled" />

</bindings><click>

<invokeMethod target="detailsView" method="moveNext" /></click>

</button>

По событиям click происходит смещение текущей записи данных в ItemView.Управление доступностью кнопки осуществляется декларативно при помощисвойств canMovePrevious и canMoveNext элементов данных. На рис. 7.7 показанаокончательная версия страницы в действии. Обратите внимание: кнопка Saveдоступна из-за наличия несохраненных изменений.

Рис. 7.7. Пример детализированного представлениясвязанных данных с панелью перемещения

Двусторонняя привязка данныхКласс ItemView наследует методы addltem и deleteCurrentltem от своего базовогокласса DataControl. Эти методы можно связать с кнопками пользовательскогоинтерфейса, инициирующими действия по вставке и удалению данных на сто-роне клиента. Оба метода реализуются классом DataControl и работают напрямую

Page 299: Microsoft ASP.NET 2.0 AJAX

Расширенные функции 2 9 9

с данными, связанными с элементом. Простое редактирование данных во второмстолбце на рис. 7.7 приведет к изменению содержимого соответствующих полейданных. Подобное поведение является следствием двусторонней привязки данных.

<textBox id="details_Contact"><bindings>

<binding dataPath="ContactName" property="text" direction="InOut" /></bindings>

</textBox>

В коде XML Script страницы, показанной на рисунке, каждое текстовое полесвязывается с полем данных через привязку типа InOut. В результате данные пе-редаются в обоих направлениях: источник данных поставляет данные для тек-стового поля, а текстовое поле обновляет содержимое источника в соответствиис правкой пользователя.

Двусторонняя привязка обеспечивает обновление клиентского кэша данныхв реальном времени. Для добавления новых и удаления существующих записейсоздаются специальные кнопки и методы:

<button id="addButton"><bindings>

<binding dataContext="dataSourcel" dataPath="isReady"property="enabled"/>

</bindings><click>

<invokeMethod target="detailsView" method="addItem" /></click>

</button><button id="delButton">

<bindings><binding dataContext="dataSourcel" dataPath="isReady"

property="enabled"/></bindings><click>

<invokeMethod target="detailsView" method="deleteCurrentItem" /></click>

</button>

Как видите, мы отслеживаем свойство isReady источника данных и временноблокируем элементы, если данные не готовы или находятся в процессе обновления.

Говоря о двустороннем связывании данных, необходимо обратить особое вни-мание на синхронизацию данных с сервером. Клиентские элементы (такие, какItemView) могут синхронизировать пользовательский интерфейс только с копиейданных из клиентского кэша. Единственным компонентом, имеющим доступк серверному хранилищу данных, является источник данных. Как было показаноранее (см. рис. 7.2), источник данных — единственный компонент, обращающий-ся к серверу через указанную службу данных. Для сохранения необработанныхизменений (правок, вставок и удалений) необходимо вызвать метод save источ-ника данных. Вот как это делается при помощи кнопки Save:

<button id="saveButton"><bindings>

Page 300: Microsoft ASP.NET 2.0 AJAX

3 0 0 Глава 7. Привязка данных на стороне клиента

<bitiding dataContext="dataSourcel" dataPath="isDirtyAndReady"property="enabled" />

</bindings><click>

<invokeMethod target="dataSourcel" method="save" /></click>

</button>

С кнопки автоматически снимается блокировка при наличии необработанныхизменений. Следующая привязка становится завершающим штрихом пользова-тельского интерфейса:

<itemView id="detailsView"><bindings>

<binding dataContext="dataSourcel" dataPath="data"property="data" />

<binding dataContext="dataSourcel" dataPath="isReady"property="enabled" />

</bindings>

</itemView>

Привязка к свойству enabled элемента ItemView заблокирует весь пользова-тельский интерфейс элемента при неготовности источника данных (то есть на товремя, пока источник обновляет серверное хранилище данных).

ЗаключениеПривязка данных заложена в основу большинства приложений, и веб-приложе-ния не являются исключением. Привязка состоит из двух основных фаз: загруз-ки информации из хранилища данных и связывания данных с элементами поль-зовательского интерфейса. Долгие годы эти задачи решались на программномуровне, написанием многих строк шаблонного кода. В какой-то момент архитек-торы и разработчики задумались, нельзя ли делать то же самое более эффектив-но. Ответом на поставленную проблему стали элементы, связанные с данными,и компоненты-источники данных, которые были по-разному реализованы в раз-ных прикладных средах и платформах.

Так возникла концепция декларативной привязки, окончательно укрепив-шаяся в ASP.NET 2.0. В сущности, речь идет об описании привязок на уровнеразметки, без традиционного программирования.

В серверной среде привязка данных не создает особых проблем независимоот того, как она реализована (на программном или декларативном уровне). В Atlasпривязка данных четко разделена на два уровня: клиентский и серверный. Все,что относится к пользовательскому интерфейсу и действиям пользователя, про-исходит на клиентском уровне; закрепление изменений становится возможнымтолько при передаче данных клиента на сервер.

Центральное место в архитектуре привязки данных Atlas занимают домашниевеб-службы. Если предпочтение отдано чисто программному подходу, разра-ботчик строит специальную веб-службу и использует ее методы для получения

Page 301: Microsoft ASP.NET 2.0 AJAX

Заключение 3 0 1

и сохранения записей. Для привязки данных к элементам используется кодJavaScript. Точка. Если вы предпочитаете обойтись без программирования Java-Script, выбирайте декларативное решение, при котором для реализации расши-ренных возможностей достаточно небольшого объема XML Script. В этом случаевсе операции загрузки и сохранения данных выполняются через объект источникаданных. В свою очередь, источник данных использует для выполнения «чернойработы» особую разновидность веб-служб — службы данных. Привязки и дейст-вия позволяют строить сложные пользовательские интерфейсы с минимальны-ми усилиями. Atlas также обеспечивает встроенную поддержку постраничноговывода и сортировки данных.

Остается ответить на один принципиальный вопрос: насколько эффективнаи производительна эта схема? Atlas — не волшебство; большей частью это кодJavaScript — язык, как известно, интерпретируемый. Все расширенные возмож-ности предоставляются библиотекой JavaScript, моделирующей управляемуюсреду .NET Framework. В одних ситуациях это вполне допустимо — например,при заполнении отдельных страниц несколькими записями данных или при по-строении гибридных приложений. Однако при значительном объеме кода (на-пример, при сортировке) стоит рассмотреть и другие, альтернативные решения.

Page 302: Microsoft ASP.NET 2.0 AJAX

ГЛАВА 8 Гаджеты AtlasВ этой главеi Что такое гаджет?i Построение гаджета Atlas

Гаджеты, или мини-приложения, приобретают все большую популярность в сооб-ществе квалифицированных пользователей Web и Microsoft Windows. Добавле-ние гаджетов поддерживается многими известными страницами, включая личнуюначальную страницу Live.com, пользовательское пространство MySpaces.com,специализированные службы типа Windows Live Mail, рабочий стол WindowsVista и даже ряд обычных блогов и веб-страниц.

Гаджеты предназначены для максимального ускорения доступа к сервису и ин-формации. Важная отличительная особенность гаджетов заключается в том, что ониориентированы на выполнение одиночных задач и прием информации в реальномвремени, в сочетании с логичным, интуитивно понятным, удобным и четким интер-фейсом. Сущность гаджетов хорошо выражена в следующей цитате из статьи «Win-dows Live Gadget Design Guide» (http://microsoftgadgets.com/livesdk/clocs/uiguicle.htm):

«Гаджет не является контейнером для нескольких разнородных функций. Еслидля работы с гаджетом потребуется пояснительный текст, вероятно, вы сделалиего слишком сложным.»

Гаджет выполняет всего одну функцию, притом делает это способом, понят-ным и удобным для пользователя. Классические примеры гаджетов — мини-при-ложения для вывода прогнозов погоды, сводок веб-новостей или отображенияслайдовых презентаций.

За последнее время многие разработчики выпустили схожие технологии.Для примера можно упомянуть Konfabulator от Yahoo!, Desktop X от Stardockи Kapsules от Shellscape. Все перечисленные продукты спроектированы для рас-ширения рабочего стола Windows, а для управления ими необходимо установитьспециализированное ядро.

Какое место гаджеты занимают в Atlas, спросите вы? Прикладная среда Atlasявляется самым простым и самым мощным инструментом для написания но-вых гаджетов.

Что такое гаджет?Архитектура гаджетов открыта для применения любых технологий. Напри-мер, гаджеты можно писать на Dynamic HTML или, еще лучше, на MicrosoftASP.NET Atlas.

Page 303: Microsoft ASP.NET 2.0 AJAX

Что такое гаджет? 3 0 3

В конечном итоге автор сам определяет, как будет работать его гаджет. На-пример, можно написать гаджет, который проверяет версию нижележащей опе-рационной системы и добавляет дополнительные эффекты GUI при работе накомпьютерах с Windows Vista. Разработчики также могут писать унифицирован-ные гаджеты, которые генерируют код Dynamic HTML и работают как в веб-страницах (скажем, Live.com), так и на боковой панели Windows Vista.

Гаджет во многом похож на приложение. Он может базироваться на платформеWindows или Web; он может работать в режиме постоянного сетевого подключе-ния, подключаться по мере необходимости или просто работать в автономномрежиме. Гаджет может передавать любую информацию (сводки, прогнозы пого-ды, новости, фотографии и т. д.), давать пользователю возможность выполнятьразличные задачи или играть в игры. При этом должно выполняться лишь одноключевое условие: гаджет должен быть направлен на решение одной первооче-редной функции. Кроме того, он должен иметь интуитивно понятный интерфейси существовать в чрезвычайно компактном пространстве.

Live.com, Windows Vista и гаджетыГаджеты могут размещаться в двух основных местах: на веб-сайте Live.com и набоковой панели Windows Vista. В обоих случаях главной целью является персо-нализация личного пространства, чтобы вся необходимая функциональностьбыла у пользователя «под рукой». Гаджеты всего лишь представляют собой раз-новидность приложений, которые работают на обеих платформах и загружаютсяиз галереи (или разрабатываются собственными силами).

Рекомендации по проектированию гаджетовГаджет — приложение узкоспециализированное, компактное, простое и обладаю-щее намеренно ограниченной функциональностью. Гаджеты проектируются такимобразом, чтобы выводимая ими информация была понятна пользователям с ми-нимальными пояснениями, а работа требовала минимальных усилий по настройкеконфигурации. Гаджет не должен быть усеченной версией более функционально-го, более мощного приложения; скорее, это мини-приложение с ограниченнымизадачами, которое иногда дополняет существующее приложение.

Гаджет хорошо вписывается в окружающие условия по своему внешнему видуи поведению и эффективно использует занимаемое пространство. В идеале вы-сота гаджета не должна превышать 200 пикселов в стандартном состоянии, и онне должен увеличиваться свыше 400 пикселов в развернутом виде.

Содержимое гаджета должно храниться готовым к отображению, чтобы поль-зователю не приходилось ожидать появления информации. Впрочем, динамиче-ская загрузка содержимого гаджета тоже допустима, если последний обеспечитсоответствующую обратную связь для пользователя.

Учтите, что некоторые гаджеты обладают ограниченным сроком жизни. Пред-ставьте, что вы установили гаджет, который выводит в реальном времени ново-сти о некотором спортивном мероприятии. Спустя несколько дней или недельпосле мероприятия у гаджета уже не будет полезной информации. В таких

Page 304: Microsoft ASP.NET 2.0 AJAX

3 0 4 Глава 8. Гаджеты Atlas

случаях гаджет должен вывести сообщение с предложением удалить себя, вместотого чтобы продолжать выводить устаревшую информацию.

Режимы работыГаджет может находиться в одном из трех режимов: запуска, свернутом и развер-нутом. Чтобы добавить свои гаджеты на боковую панель Vista или на страницуLive.com, пользователь выбирает их в каталоге.

Гаджет, находящийся в каталоге, работает в режиме запуска. В этом режимедля него выводится только значок и название. Эта информация должна быть какможно более содержательной, потому что именно она становится ключевымфактором, по которому пользователи выбирают гаджет.

Содержимое гаджета отображается в раскрывающемся окне. Когда окно за-крыто, гаджет находится в свернутом состоянии. В это время виден только заго-ловок гаджета. Как правило, заголовок включает значок и имя, но в него такжеможно включить некоторые ключевые аспекты содержимого. Например, у гаджетас прогнозом погоды в свернутом виде может показываться только текущая тем-пература и сводка погоды для отслеживаемого города или местности (рис. 8.1).

Рис. 8 . 1 . Гаджет с прогнозом погоды в свернутом состоянии

В развернутом режиме отображается полное содержимое гаджета. Высотаокна не должна превышать 400 пикселов. На рис. 8.2 показано, как гаджет с про-гнозом погоды выглядит в развернутом состоянии.

Рис. 8.2. Гаджет с прогнозом погоды в развернутом состоянии

Примеры гаджетовВ конечном итоге большинство гаджетов представляет собой гибридные прило-жения, пользующиеся поставками данных от других сайтов и веб-служб. Таквозникает пара дополнительных проблем, относящихся скорее к построениюгибридных приложений нежели к гаджетам в частности. У пользователя нико-гда не должно возникать впечатления, что гаджет не реагирует на его действия;

Page 305: Microsoft ASP.NET 2.0 AJAX

Что такое гаджет? 3 0 5

пользователь должен быть в курсе всех выполняемых действий, включая аутен-тификацию (там, где это необходимо). Если ожидаемый формат внешних дан-ных вдруг изменился или данные стали недоступными, мини-приложение должнобыть способно корректно сократить свою функциональность.

На рис. 8.3 показаны гаджеты, установленные на боковой панели WindowsVista. Боковая панель представляет собой разновидность панели задач для раз-мещения гаджетов.

Рис. 8.3. Гаджеты, устанавливаемые по умолчанию на боковой панели Windows Vista

Гаджет с прогнозом погоды в развернутом состоянии Веб-сайт Live.com (так-же известный под названием Windows Live) играет роль центральной консоли,которая может настраиваться пользователями для персонализации ряда Интернет-служб. Домашняя страница Windows Live, составленная из гаджетов, позволяетполучить доступ ко всем ежедневно используемым службам, апплетам и данным.Чтобы создать себе страницу, сделанную «по личной мерке», пользователь реги-стрируется на сайте Windows Live, а затем выбирает гаджеты из предлагаемогокаталога (рис. 8.4).

Внутреннее устройство гаджетовГаджет состоит из трех основных элементов:I манифест — XML-файл, определяющий ключевые атрибуты (значок, назва-ние и местонахождение других элементов, включая код и таблицу стилей);

Page 306: Microsoft ASP.NET 2.0 AJAX

3 0 6 Глава 8. Гаджеты Atlas

Рис. 8.4. Размещение гаджетов на домашней странице Windows Live

I код — файл со всем программным кодом, используемым для создания гаджета;I таблица стилей — необязательный файл в формате CSS (Cascading Style

Sheet), который может использоваться для настройки пользовательского ин-терфейса гаджета.При разработке любого гаджета используется HTML и сценарный код. Гад-

жет также располагает дополнительной информацией о себе самом и о системеWindows. Страница HTML, выполняемая в формате гаджета в Windows Live илина боковой панели Windows Vista, получает доступ к объектной модели, предо-ставляющей дополнительную функциональность.

Это позволяет гаджетам работать с файлами и папками Windows, отображатьграфику из пользовательской личной папки или вывести информацию о состоя-нии беспроводного соединения. Гаджет может работать с двоичными объектами,но чаще даже очень сложные и широкофункциональные гаджеты ограничивают-ся использованием сценарного кода.

Чтобы читатель получил представление о внутренней структуре гаджета, рас-смотрим пример гаджета, загруженный с сайта Microsoft Live Gallery по адресуhttp://gallery.live.com. Вот как выглядит его манифест:

<?xml version="1.0" encoding="utf-8" ?><gadget><name>Sudoku</name>

Page 307: Microsoft ASP.NET 2.0 AJAX

Что такое гаджет? 3 0 7

<namespace>microsoft.windows</namespace><versi оп>1.0.0.0</version><author name="Microsoft Corporation">

<info url="http://go.microsoft.com/fwlink/7LinkIch55696"text="gallery.live.com" />

<logo src="logo.png" /></author><copyright>&#169; 2006</copyright><description>Play Sudoku.</description>

<icons><icon height="48" width="48" src="icon.png" />

</icons><hosts>

<host name="sidebar"><base type="html" apiVersion="1.0.0" src="sudoku.html" /><permissions>full</permissions><platform minPlatformVersion ="1.0"/>

</host></hosts>

</gadget>

Страница с именем sudoku.html содержит ссылку на сценарный файл, в кото-ром определяется большая часть логики.

За дополнительной информацией о разработке гаджетов на основе HTML,кода JavaScript или двоичных объектов обращайтесь по адресу http://windowssdk.msdn.microsoft.com/en-us/library/ms723694.aspx. В этой главе будет рассказаноо том, как писать гаджеты на платформе Atlas, а также будут рассмотрены основ-ные потенциальные проблемы, на которые следует обратить внимание.

Гаджеты и AtlasПоскольку гаджеты состоят из разметки и сценарного кода, Atlas становится ес-тественным кандидатом на роль платформы разработки ¹ 1 — по крайней мере,для веб-гаджетов, работающих в Windows Live.

Почему именно Atlas?Упоминавшийся ранее гаджет Sudoku написан исключительно на JavaScript. Ондолжен поддерживать информацию состояния, принимать ввод и соответствующимобразом обновлять пользовательский интерфейс. В каждой из перечисленных об-ластей Atlas обладает значительными преимуществами. Как упоминалось в главе 5,Atlas дополняет язык JavaScript наследованием, пространствами имен и интер-фейсами. Вполне очевидно, что сложную логику проще писать на Atlas JavaScript.

Более того, службы данных, пользовательские профили, привязки, клиентскиешаблоны и элементы существенно упрощают построение расширенных поль-зовательских интерфейсов по сравнению с «обычным» кодом Dynamic HTML.И такой подход действительно оказывается эффективным. Таким образом, дан-ная платформа отлично подходит для построения сценарных гаджетов; можнопредположить, что Atlas станет главным (если не единственным) кандидатом сра-зу же после его официального выпуска.

Page 308: Microsoft ASP.NET 2.0 AJAX

3 0 8 Глава 8. Гаджеты Atlas

Страницы Atlas и гаджеты AtlasГаджет загружается в виде веб-страницы, поэтому создание гаджетов Atlas начи-нается с создания страницы Atlas. Гаджет Atlas представляет собой полнофунк-циональную страницу Atlas, которую можно протестировать локально при помо-щи веб-приложения Microsoft IIS (Microsoft Internet Information Services). Темне менее между простыми страницами Atlas и страницами, спроектированнымидля выполнения в качестве гаджетов, существует ряд различий.

Чтобы выявить эти различия и убедиться в том, что гаджет действительно рабо-тает именно так, как предполагалось, необходимо тщательно протестировать егов управляющей среде гаджета (на боковой панели Windows Vista или в WindowsLive).

Страница-гаджет Atlas должна включать специализированный элемент Gadget,причем все ссылки на сценарный код или веб-службы должны осуществлятьсячерез этот элемент, а не через ScriptManager. Элемент Gadget предоставляет шаб-лон содержимого, в котором определяется пользовательский интерфейс гаджета.Любые элементы, размещаемые за пределами Gadget, при предоставлении стра-ницы в качестве гаджета отображаться не будут. Впрочем, в шаблоне гаджета мо-гут размещаться только «натуральные» элементы, а элементы runat=server запре-щены. Итак, давайте займемся построением гаджета Atlas и разберемся со всемипотенциальными проблемами.

Построение гаджета AtlasВ целом написание гаджета принципиально не отличается от написания страни-цы Atlas, и все же остается ряд различий. В обоих случаях первым шагом должнобыть написание клиентской страницы Atlas. Как упоминалось ранее, гаджетыAtlas не могут содержать серверных элементов; это главное отличие между гад-жетами Atlas и веб-страницами. Следовательно, основу пользовательского ин-терфейса гаджетов Atlas образуют теги HTML и привязки XML Script.

Реализация гаджетаТело страницы Atlas, которая может использоваться в качестве гаджета, имеетследующую форму:

<body><form id="forml" runat="server"><div>

<atlas:ScriptManager ID="scriptManagerl" runat="server" /><atlas:Gadget runat="server" ID="Gadgetl"

Title="My First Gadget"Description^'It’s only my first try...">

<ContentTemplate><p>Hello, Gadget.</p>

</ContentTemplate>

</atlas:Gadget></form></div>

</body>

Page 309: Microsoft ASP.NET 2.0 AJAX

Построение гаджета Atlas 309

Серверный элемент Gadget определяет заголовок и описание гаджета — ин-формацию, которая будет передана в манифест. Тег ContentTemplate определяетсодержимое гаджета.

Серверный элемент GadgetСерверный элемент Gadget определяется в пространстве имен Microsoft.Web.Ulи реализуется в виде составного шаблонного элемента. На рис. 8.5 показан кон-структор элемента Gadget в Microsoft Visual Studio 2005.

Рис. 8.5. Серверный элемент Gadget в конструкторе страницы Visual Studio 2005

Все, что мы видим внутри блока Gadget, будет отображаться во время выпол-нения в Windows Live или на боковой панели. С этой точки зрения конструкторэлемента весьма удобен и интуитивно понятен. Свойства элемента Gadget пере-числены в табл. 8.1.

Обратите внимание: коллекции Scripts и Services аналогичны коллекциям, оп-ределяемым для элемента ScriptManager. В обоих случаях в коллекциях хранятсяссылки на используемые сценарные файлы и веб-службы. Однако коллекцииScripts и Services элемента ScriptManager содержат ссылки на файлы, исполь-зуемые страницей, а коллекции элемента Gadget содержат ссылки на файлы,используемые гаджетом.

Данное различие не принципиально, если страница используется в качествепростой страницы Atlas, вызываемой по гиперссылке или из браузера. Но еслистраница предоставляется пользователю как гаджет, внешние ссылки будут потеря-ны, если они не устанавливались непосредственно через элемент Gadget. В ко-нечном итоге ссылки на все файлы JavaScript, веб-службы или таблицы стилей,используемые элементом Gadget, должны подключаться через свойства элемента.

Page 310: Microsoft ASP.NET 2.0 AJAX

3 1 0 Глава 8. Гаджеты Atlas

Таблица 8 . 1 . Свойства элемента Gadget

Свойство ОписаниеContentTemplate Шаблонное свойство, опеределяющее содержимое гаджета. Шаблон

не может содержать серверных элементовDescription Описание гаджета, которое будет храниться в манифесте (чтение

и запись)Scripts Коллекция объектов ScriptReference. Содержит ссылки на все

сценарные файлы, необходимые для элемента GadgetServices Коллекция объектов ServiceReference. Содержит ссылки на все веб-

службы и мостовые файлы, необходимые для элемента GadgetStyles Коллекция объектов StyleReference. Содержит ссылки на все файлы

CSS, необходимые для элемента GadgetTitle Название гаджета, которое будет храниться в манифесте (чтение

и запись)

Подключение веб-служб, таблиц стилей и сценарных файлов может осуществ-ляться либо на программном, либо на декларативном уровне через дочерниетеги, как показано в следующем примере:

<atlas:Gadget runat="server" ID="Gadgetl"Title="My First Gadget"Description^'It’s only my first try...">

<ContentTemplate>

</ContentTemplate><Services>

<atlas:ServiceReference path="~/WebServices/MyDataService.asmx" /></Services><Scripts>

<atlas:ScriptReference path="Gadgetl.aspx.js" /></Scripts><Styles>

<atlas:StyleReference path="Gadgetl.aspx.css" /></Styles>

</atlas:Gadget>

Интересно заметить, что элемент Gadget представляет собой некое подобие«страницы в странице» — своего рода микрокосм, который должен быть полно-стью самодостаточным. Например, не допускается определение встроенного сце-нарного кода или подключение таблиц стилей на уровне страницы в теге <head>.Ответы на все «почему?» и «с какой стати?», связанные с этим требованием, ста-новятся очевидными, если заглянуть «под капот» элемента Gadget и больше уз-нать о его взаимодействии с внешней средой.

Внутреннее устройство элемента GadgetЭлемент Gadget является составным (composite) элементом ASP.NET; он насле-дует от Control и переопределяет метод CreateChildControls. Метод создает экзем-пляр свойства ContentTemplate и перебирает все свои дочерние элементы. Реали-зация на псевдокоде выглядит так:

Page 311: Microsoft ASP.NET 2.0 AJAX

Построение гаджета Atlas 311

protected override void CreateChildControlsO{

if (ContentTemplate != null)return;

// Создание экземпляра шаблонаControl container = new Control();ContentTemplate.Instantiateln(container);

// Проверка содержимого шаблонаforeach (Control ctl in container.Controls){

if (!(ctl is LiteralControl))throw new InvalidOperationExceptionC . . . " ) ;

}// Включение реализованного шаблона в дерево элементаControls.Add(container);

}

Как видно из листинга, элемент Gadget выявляет серверное содержимое и в слу-чае обнаружения чего-либо с пометкой runat=server выдает исключение. Помните,что все содержимое страницы ASP.NET, не помеченное атрибутом runat, ком-пилируется как LiteralControl. В основном это делается по соображениям быст-родействия. Впрочем, отсутствие элементов runat=server не ограничивает мощипрограммного кода. Вы по-прежнему можете строить интерактивные страницы,принимающие ввод и отвечающие на действия пользователей, — просто необхо-димо понять, что эти возможности должны кодироваться на уровне простого сце-нарного кода и тегов HTML. Вот почему Atlas со своей расширенной модельюJavaScript оказывает здесь огромную помощь.

Следующее крупное событие в жизненном цикле элемента Gadget связано состадией предварительного построения. Взгляните на псевдокод переопределен-ной версии OnPreRender:

protected override void OnPreRender(EventArgs e){

if (IsGadgetRequestO){

if (IsGadgetContentRequestO){

Page.SetRenderMethodDelegate(new RenderMethod(RenderGadgetContents));

}else{

Page.SetRenderMethodDelegate(new RenderMethod(RenderManifest));

}}else{

AddScriptsToScriptManager();AddServicesToScriptManagerO;AddStylesToPageO;

}}

Page 312: Microsoft ASP.NET 2.0 AJAX

3 1 2 Глава 8. Гаджеты Atlas

Метод сначала проверяет, поступил ли запрос от «хозяина» гаджета. Если нет,Gadget ведет себя как элемент-заполнитель и выдает свое содержимое на страни-цу. Что еще важнее, его стили, службы и сценарии просто включаются в компо-нент ScriptManager страницы.

Если запрос страницы действительно адресован элементу Gadget, метод ОпРге-Render регистрирует метод, который будет активизироваться посредством обрат-ного вызова в процессе непосредственного построения элемента. Зарегистриро-ванный метод заменяет стандартный и полностью определяет вывод элемента.Иначе говоря, когда запрос страницы поступает от «хозяина» гаджета, все содержи-мое в теле страницы игнорируется, за исключением содержимого элемента Gadget.

Существует два варианта обращения к гаджету со стороны «хозяина»: он мо-жет запросить манифест гаджета или только его содержимое. Такие специаль-ные запросы создаются посредством включения параметров в строку запроса, какпоказано в следующем примере:

http://www.contoso.com/gadgets/gadgetl.aspx?gadget=truehttp://www.contoso.com/gadgets/gadgetl.aspx?gadget=true&render=true

Оба URL ссылаются на страницу Atlas с именем gadgetl .aspx, содержащуюэлемент Gadget. Первый URL запрашивает манифест гаджета, а второй — раз-метку, внедряемую в боковую панель Windows Vista или сайт Windows Live.В предыдущем фрагменте псевдокода функция IsGadgetRequest ищет параметрgadget, а IsGadgetContentRequest ищет оба параметра, gadget и render.

Разметка, посылаемая элементом Gadget своему хозяину, выглядит так:<root><![CDATA[

<!-- Разметка элемента Gadget -->

<script type="text/xml-script"><page xmlns:script="http://schemes.microsoft.com/xml-script/2005">

<references><add src="http://.../IntroAtlas/atlasglob.axd" /><add src="http://.../IntroAtlas/Samples/Ch08/gadgetl.aspx.js" /><add src="http://.../IntroAtlas/Services/MyDataService.asmx/js" />

</references>components />

</page></script>]]></root>

Как видите, для подключения всех необходимых внешних ссылок вставляетсяспециальный тег <script>. Если, допустим, оформить сценарный код как встроен-ный, страница будет нормально работать при вызове из браузера, но выдастошибку «Object not found» при ее размещении в полноценном «хозяине» гадже-та. Код JavaScript, в котором определяется объект, не включается без явного свя-зывания через тег <Scripts>.

В конечном итоге элемент Atlas Gadget позволяет определить шаблон с содер-жимым и собирает воедино всю необходимую информацию для «хозяина», что-бы вам не приходилось создавать манифест самостоятельно.

Page 313: Microsoft ASP.NET 2.0 AJAX

Построение гаджета Atlas 313

Несколько гаджетовСтраница Atlas может содержать несколько элементов Gadget. В этом случае ка-ждый элемент Gadget должен обладать уникальным идентификатором, а синтак-сис загрузки манифеста гаджета или содержимого слегка изменяется: необходимдополнительный параметр GadgetID, идентифицирующий элемент на странице.

http://www.contoso.com/gadgets/test.aspx?gadget=true&gadgetid=MyGadgetl

Если параметр GadgetID не задан, происходит исключение типа «недопусти-мая операция».

Гаджет AmazonДавайте разработаем содержательный гаджет на основе примера с поиском книгна сайте Amazon, созданного в главе 7. Страница гаджета должна содержать ком-понент ScriptManager, но все ссылки должны быть перемещены в элемент Gadget,как показано ниже:

<atlas:Gadget runat="server" ID="AmazonFeed" Title="Amazon Gadget"Description="Book information from Amazon">

<Services><atlas:ServiceReference Path="~/WebServices/Amazon.asbx" />

</Services><Scripts>

<atlas:ScriptReference Path="amazongadget.aspx.js" /></Scripts><Styles>

<atlas:StyleReference Path="amazongadget.aspx.css" /></Styles><ContentTemplate>

</ContentTemplate></atlas:Gadget>

Содержимое гаджета копируется «один в один» из примеров главы 7. Дляподключения к веб-службе Amazon используется мостовой файл amazon.asbx,а для построения таблицы с результатами — клиентский макетный шаблон.На рис. 8.6 показан гаджет Amazon в действии на странице Windows Live.

Как загрузить гаджет в Windows Live? Именно эта тема будет рассматривать-ся в следующем разделе. С другой стороны, Windows Vista требует предвари-тельной загрузки гаджета в каталог http://gallery.live.com. Windows Vista позволя-ет добавлять гаджеты сторонних разработчиков, но вы не сможете просто ввестиURL для загрузки гаджета, как это делается в Windows Live.

ПРИМЕЧАНИЕВ сущности, гаджеты являются гибридными приложениями, потребляющими данныеот внешних поставщиков. Свяжитесь с поставщиком данных и сообщите ему, как ис-пользуются данные и какой объем дополнительного трафика следует ожидать. Гаджетдолжен содержать упоминание о поставщике данных и быть готовым среагировать,если данные вдруг станут недоступными. Наконец, не забудьте получить у поставщикаразрешение на использование содержимого.

Page 314: Microsoft ASP.NET 2.0 AJAX

3 1 4 Глава 8. Гаджеты Atlas

Рис. 8.6. Гаджет Amazon в действии

Выполнение гаджетаПосле всего, что было сказано ранее, гаджет остается веб-страницей, поэтомудля успешного и беспроблемного развертывания гаджет должен удовлетворятьряду требований к конфигурации. Давайте разберемся более подробно.

Требования IISГаджет должен быть установлен на общедоступном веб-сайте, работающем извиртуального каталога IIS. Естественно, у приложения IIS должна быть уста-новлена поддержка ASP.NET 2.0 и Atlas. Если для гаджета создается отдельнаявиртуальная папка, то от вас потребуется лишь обеспечить присутствие сборкиMicrosoft.Web.Atlas в папке Bin и включение необходимых конфигурационных дан-ных в файле web.config.

Что должно находиться в файле web.config? В двух словах, все настройки,необходимые содержащимся в гаджете средствам Atlas (таким, как конвертерыи мостовые файлы).

Как упоминалось в главе 6, последние версии Firefox и Microsoft Internet Ex-plorer 7.0 не поддерживают междоменные запросы XmlHttpRequest от доверенныхсайтов. Для работы гаджетов (и приложений Atlas вообще) необходимо вклю-чить обработчик HTTP IFrameHandler, как показано ниже:

<httpHandlers>

Page 315: Microsoft ASP.NET 2.0 AJAX

Построение гаджета Atlas 315

<add verb="*" path="iframecall.axd"type="Microsoft.Web.Services.IFrameHandler" />

</httpHandlers>

Впрочем, учтите, что этот аспект может измениться в будущих версиях Atlas.

Установка в Windows LiveУстановка гаджета в Windows Live выполняется очень просто: щелкните на ссыл-ке Add Stuff (см. рис. 8.4) и перейдите на вкладку Advanced Options. Введите URLгаджета в текстовом поле и щелкните на кнопке (рис. 8.7). Для гаджетов Atlasнеобходимо ввести URL страницы с параметром gadget=true.

Рис. 8.7. Добавление нового гаджета на домашнюю страницу Windows Live

Страница Windows Live загружает манифест сборки, после чего предлагаетпользователю просмотреть и установить его (рис. 8.8).

После выполнения всех действий новый гаджет появляется на домашнейстранице, готовый к работе.

Утечка памятиОсновной проблемой типичных веб-сайтов на базе AJAX (Asynchronous Java-Script + XML) является утечка памяти. Поскольку такие приложения в основ-ном строятся на сценарном уровне, возникает впечатление, что они лучше защи-щены от ошибок.

Page 316: Microsoft ASP.NET 2.0 AJAX

3 1 6 Глава 8. Гаджеты Atlas

Рис. 8.8. Подтверждение установки только что загруженного гаджета

Тем не менее утечка памяти в них возможна, причем отследить ее бываеточень трудно. Написание гаджетов на Atlas или в других прикладных средах позво-ляет большей частью избавиться от подобных неприятностей, так как используемыйкод Atlas хорошо написан и свято соблюдает все рекомендации. Если вы не исполь-зуете Atlas, загляните на страницу http://microsongadgets.com/livesdk/docs/default.htrnс рекомендациями по грамотному программированию гаджетов.

ЗаключениеГаджеты представляют собой миниатюрные Windows-приложения, написанныена HTML и сценарном коде. Они устанавливаются локально и размещаются нарабочем столе или боковой панели Windows Vista. Гаджеты также могут исполь-зоваться для расширения домашних страниц службы Windows Live. Процесс раз-работки гаджетов хорошо знаком любому веб-разработчику; он включает созда-ние HTML-страницы, выполняющей полезные функции, и манифеста XML дляхранения некоторых свойств гаджета (в том числе названия, значка и описания).

Page 317: Microsoft ASP.NET 2.0 AJAX

Об автореДино Эспозито (Dino Esposito) — преподаватель и консультант в области про-граммного обеспечения; живет в Риме (Италия). Является членом группы SolidQuality Learning (www.solidqualitylearning.com). Дино специализируется на техно-логиях Microsoft .NET и проводит большую часть времени за преподаваниеми консультациями в Европе и Соединенных Штатах.

За прошедшие годы Дино накопил практический опыт и квалификацию в облас-ти проектирования и построения распределенных систем для банков и страховыхкомпаний и в других областях с особенно высокими требованиями к безопасно-сти, оптимизации, производительности, масштабируемости и функциональнойсовместимости.

Ежемесячно по меньшей мере в пяти журналах и веб-сайтах по всему мирупубликуются статьи Дино по различным темам: от веб-разработки до доступак данным, от современных методов программирования до веб-служб. Дино ведетежемесячную рубрику «Cutting Edge» в MSDN Magazine (www. msdn.microsoft.com/msdnmag), рубрику «CoreCoder» в журнале asp.netPRO (www.aspnetpro.com) и бюл-летень ASP.NET-2-The-Max для Dr. Dobb’s Journal (www.ddj.com/dept/windows).Пользуясь репутацией авторитетного и признанного эксперта в области веб-прило-жений, построенных с применением технологий .NET, Дино вносит свой вкладв создание материалов Microsoft для разработчиков и IT-консультантов. Его статьи можно найти в выпусках MSDN Developer Center по таким темам, какASP.NET, безопасность (www.msdn.net.microsoft.com/aspnet), Microsoft WindowsVista и доступ к данным.

Дино написал целую серию книг, многие из которых считаются лучшими в сво-их областях — как, например, «Applied XML Programming for Microsoft® .NET»(Microsoft Press, 2002). До сих пор пользуется спросом, и что еще важнее — при-меняется разработчиками со всего мира, книга «Visual C++ Windows Shell Prog-ramming» (Apress, 1998). Она остается уникальным источником информации длявсех, кто пожелает расширить возможности операционной системы Windows.

Две последние книги Дино — «Programming Microsoft ASP.NET 2.0 Core Ref-erence» и «Programming Microsoft ASP.NET 2.0 Applications: Advanced Topics»(Microsoft Press, 2006). Обладатель звания «наиболее значимого профессионала»(MVP, Most Valuable Professional), Дино регулярно выступает на отраслевых кон-ференциях по всему миру (Microsoft TechEd, Microsoft DevDays, DevConnections,DevWeek и WinDev), а также локальных технических конференциях и собрани-ях в Европе и США.

Дино живет со своей семьей неподалеку от Рима (Италия). Столкнувшисьс особенно сложной технической проблемой, он обычно играет в теннис или за-нимается пробежками на природе. Решение, словно по волшебству, появляетсячерез несколько минут после душа, завершающего тренировку.

Page 318: Microsoft ASP.NET 2.0 AJAX

Алфавитный указательАAction, класс, 177Application, объект

findObject, метод, 173общие сведения, 167

asbx, файлы, 255atlas.js, файл, 163AutoCompleteBehavior, класс, 199

ВButton, элемент, 190

СCheckBox, элемент, 191ClickBehavior, класс, 201CustomValidator, элемент, 197

DDataControl, элемент, 273DataObjectMethod, атрибут, 282DataSource, класс, 279DataView, класс, 285

FfindObject, метод, 173FloatingBehavior, компонент, 209Function, объект, 164

GGetProfile, метод, 227

НHoverBehavior, компонент, 202Hyperlink, элемент, 191

IIFrameExecutor, 254IIS (Internet Information Services), 308Image, элемент, 192InputControl, класс, 193

InvokeMethodAction, класс, 178ItemView, элемент, 294

LLabel, элемент, 192ListView, элемент, 273Live.com, 302load, события, 174

PPopupBehavior, класс, 203PositioningMode, перечисление, 204PostBackAction, класс, 180POX (Plain Old XML), 257ProfileWebService, класс, 216propertyChanged, событие, 176

RRangeValidator, элемент, 196RegexValidator, элемент, 197RequiredFieldValidator, элемент, 195

SSelect, элемент, 192SetProfile, метод, 227SetPropertyAction, класс, 179SOAP (Simple Object Access

Protocol), 257StringBuilder, класс, 183Sys.Application, класс, 172Sys.Debug, класс, 187Sys.Profile, класс, 227Sys.Action, класс, 177Sys.Binding, класс, 266Sys.Component, класс, 175Sys.Counter, класс, 185Sys.Data.DataSource, класс, 279Sys.Data.DataView, класс, 285Sys.Net.WebRequest, класс, 187Sys.Net.WebRequestExecutor, 255

Page 319: Microsoft ASP.NET 2.0 AJAX

Sys.StringBuilder, класс, 183Sys.Timer, класс, 184Sys.UI.AutoCompleteBehavior, класс, 199Sys.UI.Button, элемент, 190Sys.UI.Control, класс, 189Sys.UI.CustomValidator, элемент, 197Sys.UI.Data.ListView, элемент, 273Sys.UI.Image, элемент, 192Sys.UI.Label, элемент, 192Sys.UI.RangeValidator, элемент, 196Sys.UI.RegexValidator, элемент, 197Sys.UI.RequiredFieldValidator, элемент, 195Sys.UI.Select, элемент, 192Sys.UI.TextBox, элемент, 193Sys.UI.TypeValidator, элемент, 197

TTextBox, элемент, 193TypeValidator, элемент, 197

Uunload, событие, 174

WWebMethod, атрибут, 217WebOperation, атрибут, 246wsdl.exe, утилита, 257

XXMLHttpExecutor, 255

Aанимация, 210аспекты поведения

автозаполнение, 199анимация, 210прозрачность, 211

аутентификация, службаweb.config, файл, 217конфигурация, 217общие сведения, 215ответы HTTP, 217

Ввеб-службы

доступ, 234мостовая технология, 255нелокальные, 253терминология, 215

вызов нелокальных веб-служб, 253

Алфавитный указатель 3 1 9

Ггаджеты

HTML, 306Windows Live, 305Windows Vista, 305общие сведения, 302развернутое состояние, 304свернутое состояние, 304утечка памяти, 315

Ддекларативные действия

Action, класс, 177InvokeMethodAction, класс, 178PostBackAction, класс, 180SetPropertyAction, класс, 179Sys.Action, класс, 177общие сведения, 177

Иисточники данных

Sys.Data.DataSource, класс, 279механика работы, 281общие сведения, 279

Кклиентская библиотека

Action, класс, 177findObject, метод, 173InvokeMethodAction, класс, 178SetPropertyAction, класс, 179StringBuilder, класс, 183Sys.Application, класс, 172Sys.Debug, класс, 187Sys.Action, класс, 177Sys.Component, класс, 175Sys.Counter, класс, 185Sys.Net.WebRequest, класс, 187Sys.Timer, класс, 184основные компоненты, 171пакетные обновления, 176привязка данных, 177

клиентские элементыSys.UI.Button, 190Sys.UI.CheckBox, 191Sys.UI.Control, 189Sys.UI.HyperLink, 191Sys.UI.Image, 192Sys.UI.Label, 192Sys.UI.Select, 192Sys.UI.TextBox, 193

Page 320: Microsoft ASP.NET 2.0 AJAX

3 2 0 Алфавитный указатель

Ммакетные шаблоны, 271мандат, 217методы страниц

WebMethod, атрибут, 217, 248объявление, 248

Ннаследование, поддержка, 169нелокальные веб-службы, 253

Ппакетное обновление, 176преобразователи, 261привязка

Amazon, пример, 276bindings, коллекция, 266DataControl, 273DataNavigator, 291DataObjectMethod, атрибут, 282ItemView, элемент, 294Sys.Binding, класс, 266Sys.Data.DataSource, класс, 279Sys.Data.DataView, класс, 285встроенные преобразователи, 269общие сведения, 177

проверка данныхSys.UI.CustomValidator, 197Sys.UI.InputControl, 193Sys.UI.RangeValidator, 196Sys.UI.RegexValidator, 197Sys.UI.RequiredFieldValidator, 195Sys.UI.TypeValidator, 197общие свещения, 193

программный интерфейс, 227простая привязка данных, 266пространства имен, 167

Ссериализация, 30сетевые исполнители, 255сложная привязка данных, 271событие

триггерное, 28состояние отображения, 30страницы и гаджеты, 306

Ттриггерное событие, 28

Уутечка памяти в гаджетах, 315