Почему возникает ошибка «Метод объекта не обнаружен» при вызове функции из модуля менеджера в 1С?

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

При разработке и доработке конфигураций 1С в режиме обычного или управляемого приложения иногда возникает неожиданное поведение: в файловой базе код отбатывает безошибочно, однако при переходе в клиент-серверный режим платформа выдает исключение вида «Метод объекта не обнаружен». Проанализируем, почему возникает эта ошибка и как её исправить на примере вызова экспортируемой функции из модуля менеджера регистра сведений.

Анализ исходного кода и проявления проблемы

Рассмотрим конкретную ситуацию. Из модуля формы справочника Номенклатура выполняется вызов метода регистра сведений ТоварыСПониженнойСтавкойПошлин:


СписокТНВЭДПереченьИзъятий = РегистрыСведений.ТоварыСПониженнойСтавкойПошлин.ЗаполнитьСписокПереченьИзъятий();

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


#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

&НаСервере
Функция ЗаполнитьСписокПереченьИзъятий() Экспорт    
    СписокТНВЭДПереченьИзъятий = Новый СписокЗначений;
    ПереченьИзъятий = ПолучитьАктуальныйПереченьИзъятий();
    СписокТНВЭДПереченьИзъятий.ЗагрузитьЗначения(ПереченьИзъятий);
    Возврат СписокТНВЭДПереченьИзъятий;
КонецФункции

#КонецЕсли

В файловом варианте работы данные команды выполняются корректно, а в клиент-серверном варианте платформа выдает исключение о том, что метод ЗаполнитьСписокПереченьИзъятий не обнаружен.

Выясняем причину ошибки

Проанализируем контексты компиляции и разницу между инструкциями препроцессора и директивами компиляции в платформе «1С:Предприятие».

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

Способ решения проблемы

Разберем по шагам, как исправить код в модуле менеджера для стабильной работы как в файловом, так и в клиент-серверном режиме.

Основное решение — удалить все директивы компиляции (&НаСервере) из модуля менеджера. Контроль доступа к коду должен осуществляться только через инструкции препроцессора.

Посмотрим на исправленный вариант модуля менеджера регистра сведений:


#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

Функция ЗаполнитьСписокПереченьИзъятий() Экспорт    
    СписокТНВЭДПереченьИзъятий = Новый СписокЗначений;
    ПереченьИзъятий = ПолучитьАктуальныйПереченьИзъятий();
    СписокТНВЭДПереченьИзъятий.ЗагрузитьЗначения(ПереченьИзъятий);
    Возврат СписокТНВЭДПереченьИзъятий;
КонецФункции

Функция ПолучитьАктуальныйПереченьИзъятий()
    Результат = Новый Массив;
    Макет = Неопределено;
    Попытка
        Макет = ЭСФСерверПовтИсп.ОбработкаОбменЭСФ().ПолучитьМакет("ПереченьИзъятий");
    Исключение
    КонецПопытки;
    
    Если Макет = Неопределено Тогда
        Возврат Результат;
    КонецЕсли;
    
    Возврат ОбщегоНазначения.ЗначениеИзСтрокиXML(Макет.ПолучитьТекст()).ВыгрузитьКолонку("КодТНВЭД");
КонецФункции

#КонецЕсли

Альтернативные варианты архитектуры

Если метод выполняет ресурсоемкие серверные операции или обращается к серверным объектам, которые недоступны на клиенте, разберем рекомендации по правильной организации кода:

  1. Вынос логики в Серверный Общий Модуль. Разместите тяжелые процедуры базы данных в общем модуле с установленными флагами Сервер и Вызов сервера. Тогда метод модуля формы сможет напрямую обращаться к серверной функции общего модуля.
  2. Вызов через серверный контекст формы. Если вызов происходит в управляемом приложении, обращайтесь к методам модуля менеджера из процедуры формы, имеющей директиву &НаСервере или &НаСервереБезКонтекста.

Резюме: Никогда не используйте директивы компиляции (начинающиеся со знака &) внутри модулей объектов и менеджеров. Для управления контекстом в них служат исключительно инструкции препроцессора (начинающиеся со знака #).

← На главную