в

Kazan Dev Alliance

Казанское Сообщество Разработчиков Программного Обеспечения

Персональный блог Александра Шера

Professional blog for .Net programmers. Main topics: Microsoft ASP.NET AJAX, WPF/E, OOP, Refactoring

Не-AJAX'овое назначение Microsoft ASP.NET AJAX

Интересно, что при всей пропаганде этой технологии, мало кто знает, что кроме AJAX-надстройки, совместимой с концепцией контролов ASP.NET, в сборку System.Web.Extensions входят контролы и интерфейсы, которые вообще никакого отношения к AJAX не имеют (более того - могут работать без добавления на страницу ScriptManager). То же самое касается и клиентских скриптов - лишь небольшая их часть посвещена AJAX. Для чего же нужно всё остальное?

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

  1. Передавать все ClientId в качестве аргументов функций. Неприятность здесь в том, что для некоторых функций число параметров может перевалить за полсотни. Работать с ними достаточно сложно, особенно в условиях отсутствия строгой типизации и интеллисенса в js (Orcas CTP - не в счет :)).
  2. Зачастую нежелание передавать огромное число параметров в качестве аргументов приводит к ещё более ужасному решению. Скрипт заносят в строковую переменную, а затем создают для каждого экземпляра контрола уникальную копию с правильными ClientId. То, что размер скрипта вырастает до невообразимых размеров, ещё пол беды. В таком скрипте совершенно невозможно разобраться. На свет появляется скрипт, весь состоящий из подобных кусков: [code language="JScript"]{22}.{13}=function(){{{3}.{17}.parent = {8}}}[/code]

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

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

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

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

К нашему счастью, всё это уже сделано. Microsoft AJAX Library (так именуется клиентская часть Microsoft ASP.NET AJAX) привнесла в яваскрипт огромное количество расширений, в результате чего стало возможно создавать классы с нормальным наследованием, делать проверку типов, порождать полноценные события, регистрировать пространство имен, и, как результат, создавать своего рода клиентские контролы. А в System.Web.Extensions есть набор классов и интерфейсов, которые позволяют легко связывать эти клиетские контролы с серверными образами.

Каковы же плюсы и минусы? На мой взгляд, главный плюс состоит в том, что клиентский код начинает разделять идеологию серверного. Все имена типов и полей классов могут быть в точности повторены на клиенте, что значительно облегчает понимание кода и не требует постоянного переключения мышления с объектно-ориентрованного подхода на процедурный и обратно. Кроме того, теперь весь яваскриптовый код может быть сосредоточен исключительно в .js-файлах. И никаких RegisterScript. А минусы... лично я для себя минусов не нашел. Если кто найдет - сообщите.

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

P.S. На последок пара ссылок по теме:
http://ajax.asp.net/docs/tutorials/ExtenderControlTutorial1.aspx
http://ajax.asp.net/docs/tutorials/IScriptControlTutorial1.aspx

 

Комментарии

 

Raimon сказал:

Интересно было бы посмотреть примеры кода, чтобы понять как же это все-таки делается.

еще, интересно каковы причины по которым не получиться (или не нужно) применять AJAX ?

March 30, 2007 1:46 PM
 

doctorsolberg сказал:

За примерами кода идем по ссылкам:)

March 30, 2007 2:45 PM
 

Aib сказал:

По поводу не-применения AJAX могу дать вот эту ссылку:

http://blogs.gotdotnet.ru/personal/allo/PermaLink.aspx?guid=3CE525DA-6190-46A0-ABFA-C6BB5B19E227

А от себя добавлю, что для меня всегда стопором к применению AJAX является вопрос "согласен ли клиент оплатить создание своих кнопок back/forward?" Ведь сделать кнопку back - это не просто подставить url, который был у ползователя 3 страницы назад. Пользователь должен увидеть страницу в точности в том виде, в котором он её видел последний раз. Делать по-тупому - при приличной нагрузке сервер просто треснет. А по-умному - требует немало человеко-часов.

March 30, 2007 3:48 PM
 

Raimon сказал:

неужели кто нибудь не сделал это "достаточно хорошо" и не выложил в инете?

March 30, 2007 5:49 PM
 

Aib сказал:

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

Можно хранить только разницу страниц, но тогда потребуется механизм, который будет по этой разнице восстанавливать поэтапно всё назад. Один раз мне пришлось этим заниматься. После 3-х месяцев извращений, придя в итоге к паттерну Command, я добился результатов. Но универсальностью там и не пахло - сохранение каждого возможного действия пользователя приходилось описывать руками.

Так что, если кто и сделал настоящий универсал, он его вряд ли выложит - больно дорогая игрушка, чтоб её на халяву отдавать. Да и потом - мало кому это нужно. В 95% случаев проще либо забить на back/forward в их "правильном" испольнении, либо забить на AJAX ;)

March 30, 2007 6:20 PM

Оставить комментарий

(required)  
(optional)
(required)  

© 2007 Kazan Developers Community and Post`s Authors