Рассмотрим весьма распространенную ситуацию: вы написали расширение для конфигурации 1С (например, для "Зарплата и Управление Персоналом"), добавили свою кнопку и логику обработки. До обновления базы всё работало корректно, однако после обновления (и повышения режима совместимости) при попытке вызова процедуры форма выдает ошибку: Метод объекта не обнаружен. Проанализируем причины такого поведения системы и разберем по шагам, как правильно адаптировать код к новым требованиям платформы.
Посмотрим на классический пример кода, который раньше работал, а теперь вызывает исключение. В клиентском контексте (например, в обработчике нажатия кнопки) мы получаем форму документа из расширения и пытаемся вызвать ее экспортную процедуру:
ФормаДокумента = ПолучитьФорму("Документ.ИзменениеШтатногоРасписания.ФормаОбъекта", ПараметрыФормы);
ФормаДокумента.упр_ДобавитьПозицииДляИзмененияШтатногоРасписания(ТаблицаИзменений);
ФормаДокумента.Открыть();
При этом сама процедура упр_ДобавитьПозицииДляИзмененияШтатногоРасписания добавлена в модуль этой управляемой формы в расширении и имеет следующие директивы компиляции:
&НаСервере
Процедура упр_ДобавитьПозицииДляИзмененияШтатногоРасписания(Знач ТаблицаИзменений, Отказ = Ложь) Экспорт
// Серверная логика обработки данных
КонецПроцедуры
До обновления конфигурации (когда режим совместимости был, например, установлен на Версия 8.3.17) этот код отрабатывал без проблем. Но после перехода на режим совместимости Версия 8.3.21 система строго отвечает: Метод объекта не обнаружен (упр_ДобавитьПозицииДляИзмененияШтатногоРасписания).
Разберем подробнее, почему платформа стала блокировать данный вызов. В старых версиях платформы 1С существовала архитектурная лазейка (недокументированная возможность), позволявшая напрямую из клиентского кода вызывать серверные экспортные методы чужой формы &НаСервере Экспорт.
Однако, согласно строгим стандартам разработки 1С, экспортные методы модуля управляемой формы должны объявляться исключительно с директивой &НаКлиенте. Начиная с версии платформы 8.3.21 (при соответствующем режиме совместимости), разработчики 1С усилили безопасность и закрыли эту брешь. Платформа теперь строго соблюдает инкапсуляцию и разделение контекстов, пресекая попытки внешнего программного кода напрямую "прыгнуть" с клиента в серверный контекст чужой формы. Внешние вызовы теперь видят только клиентские экспортные методы.
Важное примечание: Современные анализаторы кода (такие как SonarQube с плагинами для 1С или BSL Language Server) также подсвечивают объявление экспортного метода с директивой &НаСервере в модуле формы как явную архитектурную ошибку (правило ServerSideExportFormMethod).
Мы выяснили, что напрямую вызывать серверные методы формы больше нельзя. Давайте разберем несколько архитектурно верных способов решения этой задачи.
Способ 1. Создание клиентского метода-обертки в модуле формы
Если логика глубоко завязана на саму форму, самое простое решение — сделать метод-обертку с директивой &НаКлиенте, который уже внутри себя безопасно вызовет нужную серверную процедуру.
Изменим код в модуле формы нашего расширения:
&НаКлиенте
Процедура упр_ДобавитьПозицииДляИзмененияШтатногоРасписанияКлиент(Знач МассивИзменений) Экспорт
// Вызываем серверный метод из клиентского контекста самой формы
упр_ДобавитьПозицииДляИзмененияШтатногоРасписания(МассивИзменений);
КонецПроцедуры
&НаСервере
Процедура упр_ДобавитьПозицииДляИзмененияШтатногоРасписания(Знач ТаблицаИзменений, Отказ = Ложь)
// Серверная логика осталась без изменений, но убрано слово Экспорт
КонецПроцедуры
Теперь из внешнего кода мы будем вызывать именно клиентский метод:
ФормаДокумента.упр_ДобавитьПозицииДляИзмененияШтатногоРасписанияКлиент(ТаблицаИзменений);
Обратите внимание: так как вызов происходит на клиенте, передавать в параметрах ТаблицаЗначений нельзя (ограничение клиентского контекста 1С). В нашем случае переменная ТаблицаИзменений технически являлась массивом структур, что разрешено на клиенте. Обязательно учитывайте типы передаваемых параметров!
Способ 2. Вынос логики в серверный общий модуль
Рассмотрим более правильный с точки зрения архитектуры подход. Если ваша процедура работает исключительно с данными документа и не требует немедленного обновления интерфейса еще не открытой формы, логику следует вынести в общий модуль.
упр_ШтатноеРасписаниеВызовСервера).Способ 3. Использование механизма оповещений
Если необходимо передать данные в уже открытую форму из другой формы, архитектурно корректно использовать штатный механизм 1С. Посмотрим на этот алгоритм:
Оповестить:
Оповестить("упр_ДобавитьПозиции", МассивИзменений);
ОбработкаОповещения перехватываем это событие:
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "упр_ДобавитьПозиции" Тогда
упр_ДобавитьПозицииДляИзмененияШтатногоРасписания(Параметр);
КонецЕсли;
КонецПроцедуры
Анализируя изменения платформы, важно отметить еще одну важную деталь, связанную с безопасностью. Начиная с версий платформы 8.3.18 и 8.3.19 был введен запрет на использование функции Выполнить() для вызова методов расширяемой формы из расширения.
Это нововведение стало частью глобального ужесточения безопасности платформы 1С. Цель — заставить расширения взаимодействовать только с легальным, явно объявленным программным интерфейсом формы (доступным через свойство ЭтотОбъект). Поэтому, если вы пытаетесь использовать Выполнить() для обхода ограничений экспортных методов, система также выдаст ошибку. Придерживайтесь документированных архитектурных подходов, описанных в способах выше, чтобы ваш код оставался стабильным при любых обновлениях платформы.