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

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

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

В этой статье мы подробно разберем, как обойти это ограничение, обратившись к логике модуля объекта через бесконтекстный вызов &НаСервереБезКонтекста, и проанализируем различные методики передачи данных между формой и объектом. Для освоения базовых принципов взаимодействия клиента и сервера полезно изучить руководство по распределению кода в управляемых формах.

Почему возникает проблема с контекстным вызовом?

Прежде чем переходить к решениям, давайте выясним причину. Когда мы работаем с объектами метаданных, встроенными в конфигурацию, система всегда знает, где найти их код. Однако внешняя обработка — это файл. При открытии он загружается во временное хранилище. Если серверный вызов происходит в момент, когда срок жизни этого временного файла истек или контекст формы был «замусорен», платформа выдает ошибку идентификатора. Использование &НаСервереБезКонтекста помогает избежать этой проблемы, так как серверу не нужно передавать всё состояние формы, но при этом мы теряем прямую связь с РеквизитФормыВЗначение. Для более глубокого понимания разницы в скорости выполнения этих методов будет полезно изучить анализ производительности контекстных и бесконтекстных вызовов.

Способ 1. Создание нового экземпляра объекта внутри бесконтекстной процедуры

Рассмотрим основной вариант решения: пересоздание объекта обработки на стороне сервера. Поскольку в бесконтекстном методе нам недоступен текущий Объект, мы можем программно создать новый экземпляр этой же обработки. Для этого нам понадобятся данные самой обработки (двоичные данные или путь к файлу).

Проанализируем алгоритм действий:

  1. На клиенте собираем необходимые данные из реквизитов формы в Структуру.
  2. Передаем эту структуру и адрес внешней обработки в серверный метод без контекста.
  3. На сервере создаем объект, заполняем его реквизиты и вызываем нужную процедуру.

Посмотрим на пример кода для реализации этого метода:


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

&НаСервереБезКонтекста
Функция ВызватьМетодОбъектаНаСервереБезКонтекста(ПараметрыОбъекта, АдресОбработки)
    
    // Создаем экземпляр обработки по адресу во временном хранилище
    ИмяОбработки = ВнешниеОбработки.Подключить(АдресОбработки, , Ложь);
    ОбъектЭкземпляр = ВнешниеОбработки.Создать(ИмяОбработки);
    
    // Заполняем реквизиты нового объекта данными из формы
    ЗаполнитьЗначенияСвойств(ОбъектЭкземпляр, ПараметрыОбъекта);
    
    // Вызываем процедуру/функцию из модуля объекта
    Возврат ОбъектЭкземпляр.ВашаПроцедураВМодулеОбъекта();
    
КонецФункции

Способ 2. Использование временного хранилища для передачи всего объекта

Если реквизитов очень много и вручную заполнять Структуру неудобно, мы можем использовать механизм сериализации во временное хранилище. Выясним, как это работает: на клиенте мы преобразуем объект в структуру (или используем ПрименитьИзменения), помещаем в хранилище и извлекаем уже на сервере в бесконтекстном вызове.

Разберем этот процесс по шагам:

  1. Используем метод СериализаторXDTO.ЗаписатьXDTO() или просто передаем структуру всех данных.
  2. В бесконтекстном методе создаем пустой объект и заполняем его.

Важный нюанс: для внешних обработок метод РеквизитФормыВЗначение работает только внутри контекста. Поэтому «честный» перенос состояния объекта из формы в бесконтекстный вызов всегда требует ручного переприсваивания свойств или использования универсальных функций заполнения.

Способ 3. Вынос бизнес-логики в общий модуль

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

Рассмотрим преимущества этого подхода:

Посмотрим, как изменить код:


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

// В общем модуле (Сервер, Вызов сервера)
Функция РассчитатьПоказатели(Параметры) Экспорт
    // Вся логика, которая раньше была в модуле объекта
    // ...
    Возврат Результат;
КонецФункции

Рекомендации по безопасности

При использовании ВнешниеОбработки.Создать() внутри серверных методов следует помнить про Безопасный режим. Если ваша обработка запускается в защищенном режиме (например, через справочник «Дополнительные отчеты и обработки» с включенным профилем безопасности), программное создание других объектов или работа с файлами может быть запрещена. В этом случае единственным надежным вариантом остается передача данных в Общий модуль или использование контекстных вызовов с предварительной проверкой актуальности формы.

Выясним итоговый алгоритм выбора решения: если вам нужно быстро исправить ошибку «Неизвестный идентификатор формы» в существующей внешней обработке — используйте Способ 1 с пересозданием объекта. Если вы проектируете систему с нуля — старайтесь выносить тяжелую логику в общие модули, минимизируя код в модуле объекта внешней обработки.

← На главную