Игорь Чакрыгин Игорь Чакрыгин

У любой задачи существует по крайней мере одно очевидное и невероятно простое для понимания неправильное решение

ASP.NET - Использование страничных методов в элементах управления

Одной из стандартных возможностей ASP.NET являются так называемые страничные методы (Page Methods). Суть её заключается в том, что разработчик может определить в коде страницы статические методы, помеченные атрибутом WebMethod (из пространства имён System.Web.Services), которые затем могут быть вызваны из клиентского скрипта.

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

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

Коротко о страничных методах

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

Создадим мастер-страницу Default.master.

Если мы хотим, чтобы автоматически был сгенерирован весь JavaScript-код, необходимый для вызовов страничных методов, на странице обязательно необходимо разместить серверную форму и элемент управления ScriptManager, присвоив его атрибуту EnablePageMethods значение true. Если же вызывать страничные методы мы планируем каким-то другим способом, например при помощи jQuery, делать это не обязательно.

Создадим страницу Default.aspx.

В файле с кодом (Default.aspx.cs) определим статический метод GetMessage, пометив его атрибутом WebMethod.

В файле с разметкой разместим скрипт, который будет вызывать метод GetMessage и выводить результат его выполнения.

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

Теперь при открытии страницы Default.aspx на ней появится сообщение «Hello, Igor Chakrygin!».

Переносим страничные методы в элементы управления

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

Попробуем модифицировать изначальный пример.

Создадим пользовательский элемент управления Message.ascx.

В файл с кодом перенесём определение метода GetMessage.

А в файл с разметкой - скрипт, использующий страничный метод.

И наконец добавим созданный элемент управления на страницу Default.aspx.

Теперь при открытии страницы Default.aspx никакого сообщения мы не увидим. Это связанно с тем, что страничные методы могут быть объявлены только на страницах.

Заставляем страничные методы в элементах управления работать

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

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

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

Создадим в папке App_Code файл ControlWithPageMethodsBuilder.cs со сборщиком элементов управления ControlWithPageMethodsBuilder и переопределим виртуальный метод ProcessGeneratedCode, который вызывается при компиляции страницы в тот момент, когда страница ещё не скомпилирована, но уже представлена в виде дерева CodeDOM, которое можно изменить.

Этот метод должен находить все страничные методы, объявленные в добавляемом на страницу элементе управления, создавать для каждого из них дерево CodeDOM метода-обёртки и добавлять его к дереву CodeDOM класса страницы.

Метод CreateMethodWrapper должен получать метаданные о методе и создавать дерево CodeDOM для метода-обёртки (публичный, статический метод с тем же названием, параметрами, атрибутами и возвращающий результат страничного метода, определённого в элементе управления).

Желательно, чтобы метод CreateMethodWrapperAttributes полностью копировал все атрибуты исходного метода. Я решил несколько сократить код и оставил только атрибут WebMethod без параметров.

По аналогии, метод CreateMethodWrapperParameters должен создавать параметры метода-обёртки на основе метаданных исходного метода.

Метод CreateMethodWrapperStatements должен создавать вызов исходного метода с передачей ему параметров из метода-обёртки и, если исходный метод возвращает какое-то значение, сделать тоже самое.

Всё готово. Теперь, для того, чтобы использовать созданный нами сборщик элементов управления, достаточно пометить элемент управления атрибутом ControlBuilder.

После этого при открытии страницы Default.aspx на ней вновь появится сообщение «Hello, Igor Chakrygin!», хотя страничного метода GetMessage на ней нет.

Заключение

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

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

Скачать демо (ASP.NET 4.0, Web Site)

Комментариев нет :

© Игорь Чакрыгин. Все права защищены при помощи чёрной магии. Технологии Blogger.