Пять способов запустить серверный код из клиентского модуля в 1С:Предприятие 8.3
Содержание
Серверную процедуру из клиента в 1С 8.3 вызывают через директиву компиляции &НаСервере или &НаСервереБезКонтекста в модуле управляемой формы, либо через метод общего модуля, у которого в свойствах включён флажок «Вызов сервера». Клиентский код просто обращается к этому методу по имени — платформа сама выполняет его на сервере и возвращает результат. Это прямой вызов, и в 90% задач хватает именно его.
Остальные способы нужны в особых случаях. Долгий расчёт выносят в фоновое задание, чтобы не морозить форму. Вызов из сторонней программы делают через HTTP-сервис. Доработку без снятия типовой с поддержки оформляют расширением конфигурации. А запуск по расписанию, без участия пользователя, — регламентным заданием.
Ниже — все пять механизмов с кодом и границами применимости. Весь материал про управляемое приложение (интерфейс «Такси») платформы 8.3.
Что происходит, когда клиент обращается к серверу
В управляемом приложении код физически исполняется в двух местах: на тонком клиенте и на сервере 1С. Клиент рисует формы и реагирует на действия пользователя, а работа с базой — запросы, запись документов, проведение — доступна только на сервере.
Переход между ними называют серверным вызовом. Каждый такой вызов — это сетевой обмен: клиент упаковывает данные, отправляет их на сервер, ждёт ответ. Отсюда главное правило производительности: серверных вызовов должно быть как можно меньше, а данные лучше передавать пачкой, а не по одному значению в цикле.
На клиенте недоступны запросы к базе, менеджеры объектов, чтение и запись документов и справочников — всё это живёт только на сервере. Поэтому почти любая осмысленная работа с данными рано или поздно упирается в серверный вызов, и вопрос лишь в том, каким из способов ниже его оформить.
Где исполнится процедура, определяет директива компиляции:
- 🖥️
&НаКлиенте— выполняется на клиенте, есть доступ к интерактивным методам и элементам формы; - 🗄️
&НаСервере— выполняется на сервере и имеет полный доступ к данным формы (контексту), но за это контекст гоняется туда и обратно; - ⚡
&НаСервереБезКонтекста— тоже на сервере, но без данных формы: вызов легче и быстрее; - 🔁
&НаКлиентеНаСервереБезКонтекста— один и тот же текст компилируется и для клиента, и для сервера.
Если серверной процедуре не нужны реквизиты формы, всегда берите &НаСервереБезКонтекста. Передача контекста формы — самая частая причина «тормозов» на тонком клиенте и в веб-клиенте.
Способ 1. Прямой вызов через директивы и общий модуль
Это и есть тот самый «DirectCall»: клиентская процедура формы напрямую обращается к серверной процедуре той же формы.
&НаКлиенте
Процедура РассчитатьСкидку(Команда)
Скидка = РассчитатьСкидкуНаСервере(Объект.Сумма, Объект.Контрагент);
Сообщить("Скидка: " + Формат(Скидка, "ЧДЦ=2"));
КонецПроцедуры
&НаСервереБезКонтекста
Функция РассчитатьСкидкуНаСервере(Сумма, Контрагент)
Запрос = Новый Запрос;
// ... обращение к базе, расчёт ...
Возврат РезультатРасчёта;
КонецФункции
Клиент вызывает РассчитатьСкидкуНаСервере, платформа исполняет её на сервере и возвращает число. Параметры передаются в сервер по значению, результат — обратно на клиент.
Когда логика нужна во многих формах, её выносят в общий модуль. Чтобы метод такого модуля можно было дёргать прямо из клиента, в свойствах модуля включают два флажка:
Сервер— модуль компилируется для сервера;Вызов сервера— его экспортные методы можно вызывать из клиентского кода.
Тогда вызов выглядит так же просто:
&НаКлиенте
Процедура ОбновитьКурсыВалют(Команда)
РаботаСКурсамиВалют.ЗагрузитьАктуальныеКурсы();
КонецПроцедуры
Здесь РаботаСКурсамиВалют — общий модуль с флажками «Сервер» и «Вызов сервера», а ЗагрузитьАктуальныеКурсы — его экспортная процедура.
Серверный вызов копирует значения, а не передаёт их по ссылке. Если серверная процедура изменит переданный массив или структуру, на клиенте изменения не отразятся — возвращайте результат явно через Возврат или выходной параметр.
Если одну и ту же серверную функцию с одинаковыми параметрами вызывают много раз подряд (например, получение настройки по её имени), у общего модуля включают свойство Повторное использование возвращаемых значений со значением «На время вызова» или «На время сеанса». Платформа закэширует результат и лишних серверных вызовов не сделает.
Способ 2. Фоновое задание для долгих операций
Прямой вызов синхронный: пока сервер считает, форма заморожена. Для операций в несколько секунд и дольше (пересчёт итогов, массовое проведение, выгрузка) используют фоновое задание — оно выполняется в отдельном сеансе, а пользователь продолжает работать.
Фоновое задание запускают только на сервере, а исполняемый метод должен быть экспортной процедурой серверного общего модуля:
&НаСервереБезКонтекста
Функция ЗапуститьПересчёт(ПараметрыПересчёта)
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(ПараметрыПересчёта);
Задание = ФоновыеЗадания.Выполнить(
"РасчётыСервер.ПересчитатьИтоги",
МассивПараметров,
,
"Пересчёт итогов за период");
Возврат Задание.УникальныйИдентификатор;
КонецФункции
Клиент получает идентификатор и периодически проверяет состояние задания:
&НаСервереБезКонтекста
Функция ЗаданиеЗавершено(Идентификатор)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
Возврат Задание <> Неопределено
И Задание.Состояние <> СостояниеФоновогоЗадания.Активно;
КонецФункции
Состояние принимает значения Активно, Завершено, ЗавершеноАварийно, Отменено — по ним строят индикатор на форме. Запущенное задание можно прервать методом Задание.Отменить(). Возвращаемое значение напрямую из фонового задания не приходит: результат складывают во временное хранилище, регистр или реквизит и забирают после завершения.
Если в конфигурации подключена Библиотека стандартных подсистем, не пишите цикл опроса вручную — там есть готовая подсистема «Длительные операции» с методами запуска и ожидания результата. Она сама покажет пользователю прогресс.
Нюанс файловой базы: фоновые задания в ней выполняются, но ограниченно — обычно по одному за раз и в рамках подключения. Полноценная параллельная работа заданий — только в клиент-серверном варианте.
Способ 3. HTTP-сервис для вызова извне
Предыдущие способы работают внутри самой 1С. Когда серверную процедуру нужно вызвать из другой программы — сайта, мобильного приложения, стороннего сервиса — публикуют HTTP-сервис.
Порядок такой:
- В конфигураторе в ветке «HTTP-сервисы» создаётся сервис, задаётся корневой URL.
- К сервису добавляются шаблоны URL, а к каждому шаблону — методы с типом HTTP-запроса (
GET,POST,PUT,DELETE) и именем обработчика. - Обработчик — функция в модуле сервиса, которая принимает запрос и возвращает ответ. Исполняется она на сервере 1С.
Функция ОстатокТовара(Запрос)
Код = Запрос.ПараметрыЗапроса.Получить("code");
Ответ = Новый HTTPСервисОтвет(200);
Ответ.Заголовки["Content-Type"] = "application/json; charset=utf-8";
Ответ.УстановитьТелоИзСтроки("{""code"": """ + Код + """}");
Возврат Ответ;
КонецФункции
Чтобы сервис стал доступен снаружи, базу публикуют на веб-сервере: в конфигураторе Администрирование → Публикация на веб-сервере (нужен установленный IIS или Apache). После этого внешний клиент дёргает процедуру обычным HTTP-запросом по адресу вида http://сервер/имя_базы/hs/корневой_url/....
Доступ закрывают авторизацией: в настройках публикации указывают, под какой учётной записью информационной базы отрабатывает запрос — обычно по логину и паролю, которые клиент передаёт в заголовке. Права этого пользователя и ограничивают, что сервис имеет право прочитать или записать.
Для обмена в формате SOAP вместо HTTP-сервиса создают Web-сервис — логика та же, но описание интерфейса отдаётся по WSDL.
Способ 4. Вызов из внешней обработки и расширения конфигурации
Иногда серверный код нужно выполнить, не трогая основную конфигурацию. Здесь два инструмента.
Внешняя обработка (.epf) открывается через Файл → Открыть или подключается как дополнительная обработка. Модули её формы и объекта поддерживают те же директивы: процедура с &НаСервере внутри обработки честно выполнится на сервере. Своих прав обработка не добавляет — работает под текущим пользователем и не меняет структуру базы, поэтому для разовых задач и диагностики это самый быстрый путь.
Расширение конфигурации
(.cfe) — механизм появился в платформе 8.3.6. Расширение позволяет добавлять свои общие модули, формы и методы, не снимая типовую с поддержки. В нём доступны аннотации, которыми вклиниваются в существующие методы:
&Перед— выполнить свой код перед типовым методом;&После— после него;&Вместо— полностью заменить типовой метод.
Так в типовую конфигурацию встраивают собственные серверные процедуры без правки оригинала.
Есть и третий путь вызвать серверный код из внешней программы — внешнее соединение через COM-коннектор. Стороннее приложение создаёт объект V83.COMConnector, подключается к базе и дёргает экспортные методы общих модулей, у которых включён флажок «Внешнее соединение». Способ рабочий, но тяжеловесный и привязан к Windows, поэтому для новых интеграций обычно предпочитают HTTP-сервис.
Загрузка .cfe и обновление конфигурации базы — два разных шага. После добавления расширения обязательно выполните обновление конфигурации базы данных, иначе новые методы в базе не появятся.
Способ 5. Регламентное задание для запуска по расписанию
Когда серверную процедуру нужно выполнять по графику — ночная выгрузка, еженедельная сверка, периодическое обновление данных — её запускает регламентное задание.
В конфигураторе в ветке «Регламентные задания» создаётся объект, у которого указывают имя метода (экспортная процедура серверного общего модуля) и расписание запуска. Дальше платформа запускает этот метод сама, без пользователя, под служебной учётной записью.
Где выполняется расписание:
- в клиент-серверной базе регламентные задания запускает планировщик кластера серверов — независимо от того, работает кто-то в базе или нет;
- в файловой базе их выполняет сеанс пользователя, поэтому расписание отрабатывает, только пока база открыта.
Для однократного отложенного запуска регламентное задание избыточно — проще оформить его фоновым заданием. Регламентное имеет смысл там, где действие периодическое.
Как выбрать способ
| Способ | Когда применять | Внешний клиент |
|---|---|---|
| Директивы и общий модуль | обычная логика формы, нужен быстрый ответ | нет |
| Фоновое задание | долгий расчёт, чтобы не морозить форму | нет |
| HTTP-сервис | вызов из сайта, мобильного или сторонней программы | да |
| Внешняя обработка / расширение | доработка без правки типовой | нет |
| Регламентное задание | запуск по расписанию без пользователя | нет |
Типичные ошибки
🔸 «Переменная не определена (ИмяМодуля)» при вызове общего модуля с клиента. У модуля не включён флажок «Вызов сервера», поэтому на клиенте его просто не существует. Включите флажок либо вызывайте метод из серверной процедуры формы.
🔸 Обращение к Объект в процедуре &НаСервереБезКонтекста. Без контекста реквизиты формы недоступны. Передавайте нужные значения параметрами или переведите процедуру в &НаСервере, если контекст действительно нужен.
🔸 Сервер в цикле. Вызов серверной процедуры внутри цикла по строкам таблицы превращается в сотни сетевых обменов. Соберите данные в один массив или структуру и передайте за один вызов.
🔸 Фоновому заданию передана функция, а не процедура, или метод не экспортный. ФоновыеЗадания.Выполнить принимает имя экспортной процедуры серверного общего модуля — проверьте модификатор Экспорт и флажок «Сервер».
🔸 HTTP-сервис отвечает 404. База не опубликована на веб-сервере либо в адресе перепутан корневой URL. Проверьте публикацию и путь .../hs/....
🔸 Ожидание изменений в переданном объекте. Серверный вызов работает с копией значений: изменения массива или структуры на сервере на клиент сами не вернутся.
Частые вопросы
В чём разница между `&НаСервере` и `&НаСервереБезКонтекста`?
&НаСервере получает полный контекст формы (её реквизиты гоняются на сервер и обратно), а &НаСервереБезКонтекста — нет. Без контекста вызов легче, поэтому его предпочитают, если данные формы не нужны.Можно ли вызвать серверную процедуру прямо из команды формы?
&НаКлиенте. Из неё вызывают серверную процедуру той же формы или метод общего модуля с флажком «Вызов сервера» — напрямую из клиента серверный код не стартует.Почему фоновое задание не запускается в файловой базе?
Чем HTTP-сервис отличается от Web-сервиса?
Как добавить серверную процедуру в типовую, не снимая её с поддержки?
&Перед, &После или &Вместо, затем обновляете конфигурацию базы данных.