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

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

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

В этой статье мы подробно разберем, почему возникает эта проблема, как на работу кода влияют различные режимы работы платформы 1С (файловый и клиент-серверный), в чем разница между Тонким и Толстым клиентом, и как правильно оформлять модули объектов в соответствии со стандартами разработки фирмы «1С».

Анализируем исходную ситуацию

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

Код в модуле управляемой формы:


&НаКлиенте
Функция ПолучитьНастройкиСервераHTTP(СерверОбменаДанных)
    // Попытка создания объекта обработки на клиенте
    Обработка1 = Обработки.Обработка1.Создать();
    СтруктураHTTP = Обработка1.ПолучитьСтруктуруHTTP();
КонецФункции

Код в модуле объекта Обработка1:


&НаСервере
Функция ПолучитьСтруктуруHTTP() Экспорт
    // Возврат структуры с настройками подключения
    Возврат Новый Структура("Адрес, Порт", "192.168.1.1", 8080);
КонецФункции

В файловой базе данный код может успешно выполняться. Однако при переносе информационной базы на сервер «1С:Предприятия» (под управление SQL) при вызове метода ПолучитьСтруктуруHTTP() система выдает ошибку:

Метод объекта не обнаружен (ПолучитьСтруктуруHTTP)

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

---

Причина 1. Разница между файловым и клиент-серверным режимами работы

Выясним причину, почему поведение системы так кардинально отличается в зависимости от режима работы базы данных:

---

Причина 2. Ошибочное использование директив компиляции вместо инструкций препроцессора

Ключевая ошибка в приведенном коде модуля объекта — использование директивы компиляции &НаСервере. Разберем подробнее, почему это ломает логику работы системы.

В платформе 1С существуют два принципиально разных механизма управления контекстом исполнения кода:

  1. Директивы компиляции (начинаются со знака амперсанда &): К ним относятся &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста.

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

    Когда вы указываете директиву &НаСервере перед функцией в модуле объекта, платформа при компиляции этого модуля на стороне клиента просто «вырезает» (игнорирует) данную функцию. В результате на клиенте объект создается, но нужного метода в нем нет.

  2. Инструкции препроцессора (начинаются со знака решетки #): К ним относятся конструкции вида #Если Сервер Тогда ... #КонецЕсли, #Если Клиент Тогда ....

    Эти инструкции осуществляют условную компиляцию кода на этапе сборки модулей. Именно их необходимо использовать в общих модулях и модулях объектов для разделения клиентского и серверного кода.

---

Причина 3. Особенности работы модулей в Тонком и Толстом клиентах

Поведение системы также зависит от того, под каким клиентом запущено приложение:

---

Пошаговое руководство по исправлению ошибки

Рассмотрим, как правильно переписать код, чтобы он стабильно работал в любом режиме (файловом, клиент-серверном, под тонким и толстым клиентами).

Вариант 1. Перенос вызова объекта на сторону сервера (Рекомендуемый подход для управляемого приложения)

По правилам разработки управляемого приложения, создание прикладных объектов и манипуляции с ними должны происходить на сервере. Модуль управляемой формы должен лишь инициировать этот процесс.

Шаг 1. Перепишем модуль управляемой формы. Вызовем серверную функцию формы вместо создания объекта на клиенте:


&НаКлиенте
Процедура ВыполнитьПолучениеНастроек()
    // Вызываем серверный контекст формы
    СтруктураHTTP = ПолучитьСтруктуруHttpНаСервере();
    // Дальнейшая работа с полученной структурой
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСтруктуруHttpНаСервере()
    // Создаем объект обработки на сервере, где доступны все ее методы
    ОбработкаОбъект = Обработки.Обработка1.Создать();
    Возврат ОбработкаОбъект.ПолучитьСтруктуруHTTP();
КонецФункции

Шаг 2. Удалим некорректную директиву компиляции &НаСервере из модуля объекта Обработка1:


// Модуль объекта Обработка1
// Убираем директиву &НаСервере. Функция теперь компилируется в контексте вызова.
Функция ПолучитьСтруктуруHTTP() Экспорт
    Возврат Новый Структура("Адрес, Порт", "192.168.1.1", 8080);
КонецФункции

Вариант 2. Использование стандартов безопасного кодинга для модулей объектов

Если ваша конфигурация должна поддерживать работу как в управляемом режиме (Тонкий клиент), так и в обычном (Толстый клиент), необходимо защитить код модуля объекта от попыток некорректного выполнения на стороне клиента.

Для этого весь исполняемый код модуля объекта помещают в специальную обертку препроцессора. Это гарантирует, что тяжелый серверный код не попытается выполниться на клиенте в толстом приложении, а платформа не выдаст ложных ошибок при компиляции.

Разберем пример правильного оформления модуля объекта Обработка1:


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

// Данный блок кода будет скомпилирован только на сервере 
// или в контексте толстого клиента/внешнего соединения.

Функция ПолучитьСтруктуруHTTP() Экспорт
    
    // Пример безопасного формирования структуры
    ПараметрыПодключения = Новый Структура;
    ПараметрыПодключения.Вставить("Сервер", "api.service.ru");
    ПараметрыПодключения.Вставить("Порт", 443);
    ПараметрыПодключения.Вставить("ИспользоватьSSL", Истина);
    
    Возврат ПараметрыПодключения;
    
КонецФункции

#Иначе
// Если код попытаются вызвать на тонком клиенте (что недопустимо)
ВызватьИсключение "Недопустимый вызов объекта на клиенте!";
#КонецЕсли

Резюме правил для разработчика

Чтобы избежать подобных ошибок компиляции и видимости методов в будущем, рекомендуем строго придерживаться следующих правил:

← На главную