Как правильно вызывать методы общих модулей на клиенте и сервере в управляемых формах 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

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

Особенности клиент-серверных общих модулей и директивы компиляции

Выясним причину, по которой модуль с установленными флажками Клиент (управляемое приложение) и Сервер отказывается работать при вызове с клиента. В таких модулях код компилируется дважды: один экземпляр модуля формируется для выполнения на стороне клиента, а второй — на сервере.

Рассмотрим ключевые правила оформления клиент-серверных модулей:

  1. Директивы компиляции не используются в тексте общих модулей. Конструкции вроде &НаКлиенте, &НаСервере или &НаКлиентеНаСервереБезКонтекста допустимы исключительно в модулях форм и команд. Попытка установить их перед процедурой в общем модуле является синтаксической ошибкой.
  2. Код процедур должен быть универсальным. В клиент-серверном модуле размещаются алгоритмы, не зависящие от специфики платформы (строковые функции, математические расчеты, обработка универсальных коллекций). Использование таких менеджеров метаданных, как Константы, Перечисления, Справочники или Документы, на тонком клиенте невозможно. При компиляции клиентской копии модуля платформа выдаст ошибку об отсутствии переменной.
  3. Использование инструкций препроцессора. Если часть кода внутри общего модуля должна выполняться только на сервере или только на клиенте, применяют инструкции препроцессора:

#Если Сервер Тогда
    // Код, обращающийся к базе данных, константам или запросам
#КонецЕсли

Важно помнить: если функция объявлена внутри условия #Если Сервер Тогда, то на стороне клиента она физически не существует. При попытке вызвать ее из клиентской процедуры формы платформа закономерно вернет ошибку «Метод не обнаружен».

Свойства общего модуля: назначение флажка «Вызов сервера»

Проанализируем разницу между типами общих модулей и выясним, когда нужен признак Вызов сервера:

  1. Чисто серверный модуль (стоит только флаг «Сервер»). Код модуля компилируется исключительно на сервере. Вызывать его функции можно только из серверного контекста (из модуля объекта, из подписок на события или из серверных процедур формы &НаСервере). Прямой вызов с клиента запрещен.
  2. Клиент-серверный модуль (флаги «Клиент» и «Сервер»). Код модуля может исполняться и на клиенте, и на сервере, но не выполняет переход между ними. Метод, запущенный на клиенте, будет исполняться ресурсами клиентской машины.
  3. Серверный модуль с вызовом сервера (флаги «Сервер» и «Вызов сервера»). Экспортные методы такого модуля доступны для прямого обращения из клиентских процедур формы (&НаКлиенте). При обращении к функции платформа автоматически инициирует удаленный вызов процедуры (RPC) на сервер, передает параметры, выполняет код и возвращает результат на клиент.

Причина ошибки «Отсутствует отображение для типа 'УправляемаяФорма'»

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

  1. Примитивные типы (числа, строки, даты, булевы значения, Неопределено).
  2. Ссылки на объекты базы данных (например, СправочникСсылка или ДокументСсылка).
  3. Универсальные коллекции сериализуемых значений (Структура, Массив, Соответствие).
  4. Специальные прикладные типы данных форм (ДанныеФормыСтруктура, ДанныеФормыКоллекция).

Интерфейсные типы (объект УправляемаяФорма, переменная ЭтаФорма, элементы управления коллекции Элементы) принципиально не сериализуются. Они существуют только в памяти клиентского приложения. Попытка передать ЭтаФорма в параметре вызова общего модуля приводит к аварийному завершению с ошибкой передачи данных XDTO: «Отсутствует отображение для типа 'УправляемаяФорма'».

Архитектурно правильное разделение логики и интерфейса

Разберем, как правильно организовать работу алгоритма без передачи формы на сервер. Серверный модуль должен отвечать исключительно за обработку данных, а управление интерфейсом (видимостью и доступностью кнопок и полей) должно происходить на клиенте.

Рассмотрим реализацию через возврат структуры с сервера. В серверном общем модуле со свойствами Сервер и Вызов сервера объявим функцию проверки и получения настроек:


Функция ПараметрыСкладаОрганизации(Знач Организация, Знач Проверка = Ложь) Экспорт
    
    Результат = Новый Структура;
    Результат.Вставить("Успех", Истина);
    Результат.Вставить("Склад", Справочники.Склады.ПустаяСсылка());
    Результат.Вставить("НалогообложениеНДС", Неопределено);
    Результат.Вставить("Доступность", РольДоступна("ПолныеПрава"));
    
    Если Не ЗначениеЗаполнено(Организация) Или Не Константы.ИспользоватьПривязкуСкладовКВидуОрганизации.Получить() Тогда
        Возврат Результат;
    КонецЕсли;
    
    Если Организация.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо Тогда
        Результат.Склад = Константы.СкладДляОрганизацийЮрЛиц.Получить();
        Результат.НалогообложениеНДС = Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС;
    Иначе
        Результат.Склад = Константы.СкладДляОрганизацийФизЛиц.Получить();
        Результат.НалогообложениеНДС = Перечисления.ТипыНалогообложенияНДС.ПродажаНеОблагаетсяНДС;
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

Теперь посмотрим, как эта функция вызывается в модуле управляемой формы непосредственно в обработчике события &НаКлиенте:


&НаКлиенте
Процедура ОрганизацияПриИзменении(Элемент)
    
    ПараметрыСклада = мвДоработкиСервер.ПараметрыСкладаОрганизации(Объект.Организация);
    
    Если ЗначениеЗаполнено(ПараметрыСклада.Склад) Тогда
        Объект.Склад = ПараметрыСклада.Склад;
        Объект.НалогообложениеНДС = ПараметрыСклада.НалогообложениеНДС;
        
        // Управление элементами формы выполняется строго на клиенте
        Элементы.Склад.Доступность = ПараметрыСклада.Доступность;
        Элементы.НалогообложениеНДС.Доступность = ПараметрыСклада.Доступность;
    КонецЕсли;
    
КонецПроцедуры

Обработка прав доступа и ускорение чтения констант

Если рядовые пользователи получают ошибку «Нарушение прав доступа» при чтении констант, не обязательно открывать полные права на эти объекты метаданных в пользовательских ролях. В типовых сценариях достаточно:

  1. Установить общему модулю признак Привилегированный, если его код должен всегда выполняться в обход проверок прав текущего сеанса.
  2. Либо временно повышать привилегии внутри серверной функции с помощью метода УстановитьПривилегированныйРежим(Истина) перед получением значений констант и сбрасывать его в Ложь сразу после чтения.
  3. Для констант, значения которых меняются редко, включить в свойствах общего модуля Повторное использование возвращаемых значений (на время сеанса), чтобы сократить количество обращений к СУБД.
← На главную