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