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

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

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

Ограничения платформы: почему нельзя передать форму напрямую

Проанализируем технические особенности работы управляемых форм в клиент-серверной архитектуре 1С:

  1. Несериализуемость объекта формы: Тип данных УправляемаяФорма (как клиентский экземпляр, так и контекст на сервере) не поддерживает XDTO-сериализацию и маршалинг. Это означает, что форму физически невозможно передать в качестве параметра при вызове с клиента на сервер через общий модуль с признаком «Вызов сервера». При попытке передачи платформа сгенерирует исключение о недопустимом типе параметра.
  2. Разделение клиентского и серверного контекста: На клиенте доступен легковесный экземпляр формы, управляющий отображением элементов, а на сервере — полный контекст, содержащий реквизиты, прикладные объекты и доступ к базе данных. Получить серверный контекст формы (ЭтотОбъект) можно только внутри контекстных серверных процедур самой формы (с директивой &НаСервере). Общий серверный модуль не имеет прямого доступа к открытой на клиенте форме.

Схема решения через цепочку вызовов в модуле формы

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

  1. Клиентский общий модуль вызывает экспортную процедуру модуля формы на клиенте.
  2. Клиентская процедура формы вызывает внутреннюю серверную процедуру формы с директивой &НаСервере, перенося выполнение в серверный контекст формы.
  3. Серверная процедура формы вызывает процедуру общего серверного модуля и передает в нее параметр ЭтотОбъект (серверный контекст формы).

Посмотрим на пример реализации кода в модуле формы:


&НаКлиенте
Экспортная Процедура ВыполнитьОбработкуФормыКлиент() Экспорт
    ВыполнитьОбработкуФормыНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьОбработкуФормыНаСервере()
    // Передаем контекст текущей формы в общий серверный модуль
    МойСерверныйМодуль.ОбработатьКонтекстФормы(ЭтотОбъект);
КонецПроцедуры

Теперь рассмотрим реализацию принимающей процедуры в общем серверном модуле МойСерверныйМодуль:


Процедура ОбработатьКонтекстФормы(ФормаКонтекст) Экспорт
    // Здесь доступен полный контекст серверной формы
    Реквизит = ФормаКонтекст.Объект;
    // Выполнение необходимых серверных действий
КонецПроцедуры

А вызов из общего клиентского модуля будет выглядеть следующим образом:


Процедура ОбработатьСобытие(Форма) Экспорт
    // Вызываем экспортный клиентский метод формы
    Форма.ВыполнитьОбработкуФормыКлиент();
КонецПроцедуры

Рекомендуемые архитектурные подходы

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

1. Использование механизма расширений конфигурации

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


&Вместо("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ПродолжитьВызов(Отказ, СтандартнаяОбработка);
    МойСерверныйМодульРасширения.ОбработатьФорму(ЭтотОбъект);
КонецПроцедуры

2. Деконтекстуализация: передача данных вместо формы

В большинстве случаев серверному коду не требуется весь контекст формы целиком. Гораздо эффективнее передавать только необходимые данные:

  1. На клиенте собираем требуемые реквизиты в сериализуемую структуру (например, Ссылка, массив выбранных строк, значения ключевых полей).
  2. Передаем структуру в общий серверный модуль с признаком «Вызов сервера».
  3. На сервере выполняем необходимые операции с объектами базы данных через Ссылка.ПолучитьОбъект() или запросы и возвращаем результат клиенту.
  4. Клиентский модуль применяет полученный результат к элементам формы.

Посмотрим на пример такого взаимодействия:


// В общем клиентском модуле
Процедура ОбработатьДанныеФормы(Форма) Экспорт
    Параметры = Новый Структура;
    Параметры.Вставить("СсылкаНаДокумент", Форма.Объект.Ссылка);
    Параметры.Вставить("Комментарий", Форма.Объект.Комментарий);
    
    Результат = МойСерверныйМодульВызовСервера.ВыполнитьОперацию(Параметры);
    
    // Применяем результат на клиенте
    Форма.Элементы.ГруппаРезультат.Видимость = Результат.Успешно;
КонецПроцедуры

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

← На главную