Разработка и Конфигурация · 10 мин
Как из клиентского общего модуля вызвать серверную функцию в 1С
Как вызвать серверную функцию из клиентского общего модуля в 1С: флаги модуля, вызов сервера, передача параметров, типичные ошибки и проверка результата.
Клиентский общий модуль в 1С не может напрямую обращаться к базе данных: запросы, работа с объектами данных и большинство прикладной логики доступны только на сервере. Поэтому типовая задача — из клиентского контекста вызвать серверную функцию, получить результат и продолжить работу на клиенте. Делается это через обычный вызов экспортной функции серверного общего модуля, но с обязательным соблюдением ряда условий по флагам модулей.
Ключевое условие: серверный общий модуль должен иметь установленный флаг «Вызов сервера», а вызываемая функция — ключевое слово «Экспорт». Если хотя бы одно из условий не выполнено, на клиенте возникнет ошибка «Процедура или функция с указанным именем не определена» либо модуль просто будет недоступен для вызова.
Ниже разобраны настройка модулей, синтаксис вызова, передача параметров, особенности тонкого и веб-клиента, а также типичные ошибки, из-за которых вызов «не работает», хотя код написан правильно.
Какие флаги должны быть у серверного общего модуля
В конфигураторе откройте свойства общего модуля (правый клик по модулю → «Свойства»). Для модуля, функции которого вызываются с клиента, нужны следующие установки:
- Сервер — установлен. Модуль компилируется в серверном контексте.
- Вызов сервера — установлен. Именно этот флаг разрешает обращение к экспортным методам модуля из клиентского кода.
- Клиент (обычное приложение) и Клиент (управляемое приложение) — сняты. Если их оставить, модуль скомпилируется и на клиенте, что может привести к ошибкам компиляции при использовании серверных типов (запросов, менеджеров объектов).
- Привилегированный режим — по необходимости. Устанавливайте, только если функция должна обращаться к данным, на которые у пользователя нет прав. Это важное решение с точки зрения безопасности.
Клиентский общий модуль, из которого выполняется вызов, должен иметь флаг «Клиент (управляемое приложение)» (и «Клиент (обычное приложение)», если поддерживается обычное приложение). Флаг «Сервер» у него снимается, если модуль не нужен в серверном контексте.
Минимальный пример вызова
Создайте общий модуль, например РаботаСДаннымиСервер, с флагами «Сервер» и «Вызов сервера». В нём объявите экспортную функцию:
Функция ПолучитьЦенуНоменклатуры(Номенклатура) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура = &Номенклатура) КАК Цены";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Возврат 0;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.Цена;
КонецФункции
В клиентском общем модуле вызов выглядит как обычное обращение к функции по имени модуля:
Функция ПолучитьЦенуДляФормы(Номенклатура) Экспорт
Возврат РаботаСДаннымиСервер.ПолучитьЦенуНоменклатуры(Номенклатура);
КонецФункции
Платформа сама выполняет серверный вызов: клиентский код «не знает», что функция исполняется на сервере. Синтаксически это выглядит как локальный вызов, но физически происходит обращение клиента к серверу с передачей параметров и возвратом результата.
Какие параметры можно передавать между клиентом и сервером
Между клиентом и сервером данные передаются сериализацией, поэтому не любой тип допустим. Безопасно передавать примитивные типы (число, строка, дата, булево), ссылки на объекты базы данных, структуры, массивы, соответствия — при условии, что вложенные значения тоже сериализуемы.
Нельзя передавать объекты, существующие только в одном контексте: наборы записей, объекты типа «СправочникОбъект», построители запросов, элементы форм. Если нужно изменить объект на сервере, передайте его ссылку, а на сервере получите объект методом ПолучитьОбъект().
Особый случай — объекты СКД и табличные документы: они сериализуются, но передача больших объёмов данных между клиентом и сервером замедляет работу. Если функция возвращает, например, таблицу значений, учитывайте, что на тонком и веб-клиенте тип «ТаблицаЗначений» недоступен напрямую — возвращайте массив структур.
Особенности тонкого и веб-клиента
На тонком и веб-клиенте каждый вызов серверной функции — это сетевое обращение. Если клиентский модуль вызывает серверную функцию в цикле (например, для каждой строки таблицы), форма будет заметно «подвисать». Правильный подход — собрать все данные в массив или структуру и выполнить один серверный вызов, который обработает пакет целиком.
Директивы компиляции в клиентском модуле (&НаКлиенте, &НаСервере) в общих модулях обычно не используются — контекст определяется флагами модуля. Но внутри клиентского модуля можно использовать инструкции препроцессора #Если ТонкийКлиент Тогда, если поведение должно отличаться.
Если серверная операция длительная (загрузка данных, массовая обработка), синхронный вызов заблокирует интерфейс пользователя. В таких случаях вместо прямого вызова серверной функции используют фоновые задания с длительными операциями БСП или механизм ДлительныеОперации, а клиент периодически проверяет готовность результата.
Проверка результата и отладка вызова
После настройки модулей проверьте вызов по шагам. Сначала убедитесь, что конфигурация обновлена без ошибок компиляции: синтаксическая ошибка в серверном модуле может проявиться именно как недоступность метода на клиенте. Затем поставьте точку останова внутри серверной функции и запустите отладку — отладчик должен остановиться на серверном коде при вызове с клиента.
Если точка останова не срабатывает, проверьте: включён ли в отладке серверный контекст (в конфигураторе есть отдельная настройка отладки по протоколу HTTP/TCP и предметов отладки «Сервер»), обновлена ли база после изменения флагов модуля, не вызывается ли на самом деле одноимённая функция из другого модуля.
Как проверить результат
Функция выполняется, возвращается ожидаемое значение
Ошибка «Процедура или функция с указанным именем не определена» — проверьте флаг «Вызов сервера» и слово «Экспорт»
На сервер приходят те же значения, что отправлены с клиента
Ошибка преобразования данных — в параметрах несериализуемый тип
Функция возвращает данные в рамках прав пользователя
Пустой результат или ошибка доступа — проверьте роли либо осознанно включите привилегированный режим
Альтернативы: когда прямой вызов не лучший вариант
Прямой вызов серверного общего модуля — не единственный способ выполнить серверную логику с клиента. Если код относится к конкретной форме, логичнее разместить серверную функцию в модуле этой формы с директивой &НаСервере или &НаСервереБезКонтекста и вызывать её из клиентской процедуры той же формы. Вариант «без контекста» предпочтительнее: он не тянет за собой сериализацию данных формы.
Для логики, привязанной к объекту (например, специфическое чтение данных документа), подходит модуль менеджера объекта: Документы.РеализацияТоваров.ПолучитьДанные(Ссылка). Менеджеры всегда исполняются на сервере, и отдельный серверный общий модуль не нужен.
Сравнение вариантов
Универсальный вариант для переиспользуемой логики; требует аккуратной настройки флагов
Подходит, если логика нужна только одной форме; не работает из общих клиентских модулей
Правильное место для логики конкретного вида документов или справочников; вызывается через имя менеджера
Для тяжёлых операций, чтобы не блокировать интерфейс; сложнее в реализации
Частые вопросы
Почему клиент пишет «Процедура или функция не определена», хотя функция есть?
Чаще всего не установлен флаг «Вызов сервера» у серверного модуля или пропущено слово «Экспорт» у функции. Реже — конфигурация базы данных не обновлена после изменений, либо есть синтаксическая ошибка в самом серверном модуле, из-за которой он не компилируется.
Можно ли вызвать серверную функцию асинхронно?
Прямой вызов общего серверного модуля всегда синхронный. Для асинхронного выполнения используются фоновые задания (в типовых конфигурациях — механизм длительных операций БСП): клиент запускает задание и периодически опрашивает его состояние через обработчик ожидания.
Работает ли вызов сервера из модуля команды?
Да. Модуль команды исполняется на клиенте (если не указано иное), и из него можно вызвать экспортную функцию серверного общего модуля с флагом «Вызов сервера» точно так же, как из клиентского общего модуля.
Что вернуть с сервера вместо таблицы значений для тонкого клиента?
Обычно возвращают массив структур: каждая строка таблицы преобразуется в структуру с одинаковыми ключами. На клиенте массив обходится циклом. Это сериализуемый и безопасный для всех видов клиентов вариант.
Нужно ли ставить флаг «Клиент» у серверного модуля?
Нет. Если модуль предназначен только для серверных вызовов, флаги клиентских контекстов следует снять — иначе модуль будет компилироваться и на клиенте, а серверные типы (запросы, менеджеры объектов) вызовут ошибки компиляции в клиентском контексте.
Безопасно ли вызывать серверные функции с клиента?
Сам механизм безопасен, но разработчик отвечает за проверку прав и входных данных: серверная функция, доступная с клиента, потенциально доступна любому пользователю. Валидируйте параметры на сервере и не используйте привилегированный режим без необходимости.
Что важно запомнить
Серверный модуль должен иметь флаги «Сервер» и «Вызов сервера», функция — слово «Экспорт». Передавайте только сериализуемые типы (ссылки вместо объектов), избегайте вызовов в цикле, а привилегированный режим включайте осознанно. Для тяжёлых операций используйте фоновые задания вместо прямого вызова.