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