Как правильно вызвать серверную процедуру из клиентской в общем модуле 1С?

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

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

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

Почему возникает ошибка: внутренняя механика платформы

Рассмотрим, что происходит, когда в свойствах общего модуля одновременно включены флаги «Клиент (управляемое приложение)» и «Сервер»:

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

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

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

  1. Создадим общий модуль с суффиксом ВызовСервера (например, ОбщегоНазначенияВызовСервера).
  2. В палитре свойств нового модуля установим флаги:

    «Сервер» — включен.

    «Вызов сервера» — включен.

    «Клиент (управляемое приложение)» — выключен.

  3. Перенесем в него серверную экспортную процедуру:
    
    Процедура ВыполнитьСервернуюОперациюНаСервере(Параметр1) Экспорт
        
        // Серверная логика, работа с базой данных
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   Номенклатура.Ссылка КАК Ссылка
            |ИЗ
            |   Справочник.Номенклатура КАК Номенклатура";
        
        Результат = Запрос.Выполнить();
        
    КонецПроцедуры
    
  4. В исходном клиентском модуле вызовем процедуру через обращение к новому серверному модулю:
    
    Процедура КлиентскаяПроцедура() Экспорт
        
        ПараметрДанных = "ТестовоеЗначение";
        
        // Вызов серверного модуля
        ОбщегоНазначенияВызовСервера.ВыполнитьСервернуюОперациюНаСервере(ПараметрДанных);
        
    КонецПроцедуры
    

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

Проанализируем ситуацию, когда алгоритм не обращается к базе данных и не требует переключения контекста между клиентом и сервером. Это могут быть математические расчеты, обработка строк, преобразование дат или работа со структурами данных.

В таком случае правильным решением является создание единого универсального модуля:

  1. В свойствах общего модуля включаем флаги «Клиент (управляемое приложение)» и «Сервер».
  2. Снимаем флаг «Вызов сервера».
  3. Убираем из модуля директивы компиляции (&НаКлиенте, &НаСервере) и конструкции препроцессора. Код процедур пишется на чистом клиент-серверном подмножестве языка 1С.
  4. Пример универсального кода:
    
    Функция СформироватьСтроку(Значение1, Значение2) Экспорт
        
        Возврат СокрЛП(Значение1) + " / " + СокрЛП(Значение2);
        
    КонецФункции
    
    Процедура ОбработатьДанные(СтруктураДанных) Экспорт
        
        РезультатСтрока = СформироватьСтроку(СтруктураДанных.Поле1, СтруктураДанных.Поле2);
        СтруктураДанных.Вставить("ПолноеНаименование", РезультатСтрока);
        
    КонецПроцедуры
    

В таком варианте процедура ОбработатьДанные доступна и на клиенте, и на сервере без дополнительных сетевых вызовов, локально в том контексте, где она была вызвана.

Стандарты разделения общих модулей в 1С

Посмотрим на общую классификацию общих модулей, принятую в типовых конфигурациях 1С:

  1. Модули с суффиксом КлиентСервер: флаги Клиент (управляемое приложение) и Сервер. Служат для вспомогательных вычислений, валидации структур и строк без обращения к базе данных. Флаг Вызов сервера отключен.
  2. Модули с суффиксом ВызовСервера: флаги Сервер и Вызов сервера. Представляют собой тонкий API-фасад для вызова серверного функционала из клиентских модулей и форм.
  3. Модули с суффиксом Сервер (или без суффикса): флаг Сервер. Содержат основную бизнес-логику, недоступную напрямую с клиента.
  4. Модули с суффиксом Клиент: флаг Клиент (управляемое приложение). Содержат логику открытия окон, интерфейсных вопросов и взаимодействия с пользователем.

Важные ограничения при вызовах сервера с клиента

Рассмотрим ключевые технические ограничения, о которых необходимо помнить при вызове процедур через модули с признаком «Вызов сервера»:

  1. Мутабельные типы данных. Через границу клиент-сервер запрещено передавать объекты, не поддерживающие сериализацию: СправочникОбъект, ДокументОбъект, ТаблицаЗначений, ДеревоЗначений. В параметры серверных процедур можно передавать только ссылки (СправочникСсылка, ДокументСсылка), примитивные типы (число, строка, дата, булево), а также универсальные коллекции (Структура, Массив, Соответствие).
  2. Производительность сетевого взаимодействия. Каждый вызов серверного модуля с клиента инициирует сетевой пакет. Нельзя вызывать процедуры модулей *ВызовСервера внутри циклов клиентского кода. Если требуется обработать набор данных, формируйте массив или структуру на клиенте и передавайте их на сервер одним вызовом.
← На главную