При переходе к разработке на управляемых формах программисты часто сталкиваются с непониманием того, как разграничиваются клиентский и серверный контексты в общих модулях. Типичные проблемы проявляются в виде ошибок компиляции «Метод не обнаружен», «Переменная не определена» или ошибок сериализации при передаче параметров между клиентом и сервером. Разберем по шагам, как устроены общие модули, в каких случаях применяются те или иные свойства метаданных и как проектировать серверные вызовы без передачи контекста формы.
Выясним причину, по которой модуль с установленными флажками Клиент (управляемое приложение) и Сервер отказывается работать при вызове с клиента. В таких модулях код компилируется дважды: один экземпляр модуля формируется для выполнения на стороне клиента, а второй — на сервере.
Рассмотрим ключевые правила оформления клиент-серверных модулей:
&НаКлиенте, &НаСервере или &НаКлиентеНаСервереБезКонтекста допустимы исключительно в модулях форм и команд. Попытка установить их перед процедурой в общем модуле является синтаксической ошибкой.Константы, Перечисления, Справочники или Документы, на тонком клиенте невозможно. При компиляции клиентской копии модуля платформа выдаст ошибку об отсутствии переменной.
#Если Сервер Тогда
// Код, обращающийся к базе данных, константам или запросам
#КонецЕсли
Важно помнить: если функция объявлена внутри условия #Если Сервер Тогда, то на стороне клиента она физически не существует. При попытке вызвать ее из клиентской процедуры формы платформа закономерно вернет ошибку «Метод не обнаружен».
Проанализируем разницу между типами общих модулей и выясним, когда нужен признак Вызов сервера:
&НаСервере). Прямой вызов с клиента запрещен.&НаКлиенте). При обращении к функции платформа автоматически инициирует удаленный вызов процедуры (RPC) на сервер, передает параметры, выполняет код и возвращает результат на клиент.Посмотрим на распространенную ошибку, возникающую при попытке передать форму целиком в серверный метод общего модуля. При прямом серверном вызове с клиента на сервер платформа выполняет сериализацию данных через механизм XDTO. Сериализованы могут быть только значения определенных типов:
Неопределено).СправочникСсылка или ДокументСсылка).Структура, Массив, Соответствие).ДанныеФормыСтруктура, ДанныеФормыКоллекция).Интерфейсные типы (объект УправляемаяФорма, переменная ЭтаФорма, элементы управления коллекции Элементы) принципиально не сериализуются. Они существуют только в памяти клиентского приложения. Попытка передать ЭтаФорма в параметре вызова общего модуля приводит к аварийному завершению с ошибкой передачи данных XDTO: «Отсутствует отображение для типа 'УправляемаяФорма'».
Разберем, как правильно организовать работу алгоритма без передачи формы на сервер. Серверный модуль должен отвечать исключительно за обработку данных, а управление интерфейсом (видимостью и доступностью кнопок и полей) должно происходить на клиенте.
Рассмотрим реализацию через возврат структуры с сервера. В серверном общем модуле со свойствами Сервер и Вызов сервера объявим функцию проверки и получения настроек:
Функция ПараметрыСкладаОрганизации(Знач Организация, Знач Проверка = Ложь) Экспорт
Результат = Новый Структура;
Результат.Вставить("Успех", Истина);
Результат.Вставить("Склад", Справочники.Склады.ПустаяСсылка());
Результат.Вставить("НалогообложениеНДС", Неопределено);
Результат.Вставить("Доступность", РольДоступна("ПолныеПрава"));
Если Не ЗначениеЗаполнено(Организация) Или Не Константы.ИспользоватьПривязкуСкладовКВидуОрганизации.Получить() Тогда
Возврат Результат;
КонецЕсли;
Если Организация.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо Тогда
Результат.Склад = Константы.СкладДляОрганизацийЮрЛиц.Получить();
Результат.НалогообложениеНДС = Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС;
Иначе
Результат.Склад = Константы.СкладДляОрганизацийФизЛиц.Получить();
Результат.НалогообложениеНДС = Перечисления.ТипыНалогообложенияНДС.ПродажаНеОблагаетсяНДС;
КонецЕсли;
Возврат Результат;
КонецФункции
Теперь посмотрим, как эта функция вызывается в модуле управляемой формы непосредственно в обработчике события &НаКлиенте:
&НаКлиенте
Процедура ОрганизацияПриИзменении(Элемент)
ПараметрыСклада = мвДоработкиСервер.ПараметрыСкладаОрганизации(Объект.Организация);
Если ЗначениеЗаполнено(ПараметрыСклада.Склад) Тогда
Объект.Склад = ПараметрыСклада.Склад;
Объект.НалогообложениеНДС = ПараметрыСклада.НалогообложениеНДС;
// Управление элементами формы выполняется строго на клиенте
Элементы.Склад.Доступность = ПараметрыСклада.Доступность;
Элементы.НалогообложениеНДС.Доступность = ПараметрыСклада.Доступность;
КонецЕсли;
КонецПроцедуры
Если рядовые пользователи получают ошибку «Нарушение прав доступа» при чтении констант, не обязательно открывать полные права на эти объекты метаданных в пользовательских ролях. В типовых сценариях достаточно:
УстановитьПривилегированныйРежим(Истина) перед получением значений констант и сбрасывать его в Ложь сразу после чтения.