К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как передать параметр с клиента на сервер в 1С

Разбираем, как передать параметр с клиента на сервер в 1С: серверные вызовы, параметры формы, фоновые задания. Примеры кода, типичные ошибки и проверка результата.

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

Ключевое ограничение: передавать можно только сериализуемые данные — примитивные типы, структуры, массивы, таблицы значений. Ссылки на объекты базы данных передаются свободно, а вот «живые» объекты (ДокументОбъект, СправочникОбъект) между контекстами не передаются — на сервер их нужно получать заново по ссылке.

Ниже разобраны основные способы передачи параметров с клиента на сервер, условия выбора каждого из них, примеры кода и типичные ошибки, которые приводят к потере данных или лишним серверным вызовам.

Как устроено взаимодействие клиента и сервера в 1С

В управляемых формах код делится директивами компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста. Клиентский код работает на компьютере пользователя (или в веб-браузере) и не имеет прямого доступа к базе данных. Серверный код выполняется на сервере 1С:Предприятия и может читать и писать данные.

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

Передача параметра через серверную процедуру формы

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

&НаКлиенте

Процедура РассчитатьСкидку(Команда)

Результат = ПолучитьСкидкуНаСервере(Объект.Контрагент, Объект.СуммаДокумента);

Объект.Скидка = Результат;

КонецПроцедуры

&НаСервере

Функция ПолучитьСкидкуНаСервере(Контрагент, Сумма)

// серверный код: запрос к базе, расчет

Возврат Скидка;

КонецФункции

Если процедуре не нужны данные формы (реквизиты, элементы), объявляйте её с директивой &НаСервереБезКонтекста. Такой вызов дешевле: платформа не сериализует весь контекст формы, а передает только явные параметры. Это заметно ускоряет работу «тяжелых» форм с большим числом реквизитов.

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

1c
&НаСервереБезКонтекста
Функция ПолучитьЦену(Номенклатура, Дата)
    Запрос = Новый Запрос("ВЫБРАТЬ Цена ИЗ РегистрСведений.Цены.СрезПоследних(&Дата, Номенклатура = &Ном)");
    Запрос.УстановитьПараметр("Дата", Дата);
    Запрос.УстановитьПараметр("Ном", Номенклатура);
    Выборка = Запрос.Выполнить().Выбрать();
    Возврат ?(Выборка.Следующий(), Выборка.Цена, 0);
КонецФункции

Вызов серверных функций общих модулей

Когда логика нужна в нескольких формах, её выносят в общий модуль. Чтобы клиент мог вызвать серверную функцию общего модуля, у модуля должны быть установлены флажки Сервер и Вызов сервера. Без второго флажка вызов с клиента выдаст ошибку «Процедура или функция с указанным именем не определена».

Вызов выглядит так:

&НаКлиенте

Процедура ЗаполнитьДанные(Команда)

ПараметрыРасчета = Новый Структура;

ПараметрыРасчета.Вставить("Организация", Объект.Организация);

ПараметрыРасчета.Вставить("Период", Объект.Дата);

Результат = РасчетыСервер.ВыполнитьРасчет(ПараметрыРасчета);

КонецПроцедуры

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

Передача параметров при открытии формы

Если данные нужно передать не в текущую, а в открываемую форму, используются параметры формы. На клиенте формируется структура и передается в ОткрытьФорму():

&НаКлиенте

Процедура ОткрытьПодбор(Команда)

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Склад", Объект.Склад);

ПараметрыФормы.Вставить("ТолькоВНаличии", Истина);

ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора",

ПараметрыФормы, ЭтотОбъект);

КонецПроцедуры

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

Проверка результата: в ПриСозданииНаСервере значение читается как Параметры.Склад. Если параметр не передан, обращение к несуществующему ключу вызовет ошибку — поэтому перед использованием проверяйте Параметры.Свойство("Склад").

Передача параметров в фоновое задание

Длительные операции (загрузка данных, массовые расчеты, формирование отчетов) нельзя выполнять синхронным серверным вызовом — форма «зависнет» на время выполнения. В этом случае параметры передаются в фоновое задание через ДлительныеОперации.ВыполнитьВФоне() (в конфигурациях на БСП) или напрямую через ФоновыеЗадания.Выполнить():

&НаКлиенте

Процедура ЗагрузитьДанные(Команда)

ПараметрыПроцедуры = Новый Структура;

ПараметрыПроцедуры.Вставить("Организация", Объект.Организация);

ПараметрыПроцедуры.Вставить("ИмяФайла", ИмяФайла);

ДлительныеОперации.ВыполнитьВФоне(

"Обработки.ЗагрузкаДанных.ВыполнитьЗагрузку",

ПараметрыПроцедуры);

КонецПроцедуры

Ограничение: в фоновое задание передаются только сериализуемые значения, и результат возвращается не напрямую, а через временное хранилище (ПоместитьВоВременноеХранилище) или механизм ожидания завершения БСП. Файл с клиента в фоновое задание напрямую не передается — сначала файл помещается во временное хранилище с клиента, а на сервер передается адрес хранилища.

Передача файла с клиента на сервер
  1. 1
    На клиенте вызовите НачатьПомещениеФайлаВХранилище() и получите адрес временного хранилища
  2. 2
    Передайте адрес хранилища параметром в серверную процедуру или фоновое задание
  3. 3
    На сервере получите двоичные данные: ПолучитьИзВременногоХранилища(Адрес)
  4. 4
    Обработайте данные и удалите их из хранилища после использования
  5. 5
    Проверьте результат: на сервере данные доступны как ДвоичныеДанные, размер совпадает с исходным файлом

Какие типы данных можно передавать, а какие нельзя

Не все типы 1С переживают переход между клиентом и сервером. Ошибка «Ошибка передачи данных между клиентом и сервером» почти всегда означает попытку передать несериализуемый объект.

Тип данныхПередаетсяКомментарий
Число, Строка, Дата, БулевоДаБез ограничений
Структура, Массив, СоответствиеДаЕсли внутри только сериализуемые типы
Ссылки (СправочникСсылка и т.п.)ДаНа сервере объект получают через Ссылка.ПолучитьОбъект()
ТаблицаЗначений, ДеревоЗначенийДаС ограничениями по типам колонок
Объекты (ДокументОбъект и т.п.)НетПередавайте ссылку, объект создавайте на сервере
Запрос, ПостроительЗапроса, COMОбъектНетСоздаются заново в нужном контексте
ДанныеФормы, элементы формыНетДоступны только в контексте формы
Типичные ошибки
01
Попытка передать ДокументОбъект с клиента на сервер — ошибка сериализации; передавайте ссылку и получайте объект на сервере
02
Серверный вызов внутри цикла по строкам таблицы — десятки сетевых обменов; соберите данные в массив или таблицу и передайте одним вызовом
03
Обращение к Параметры.ИмяПараметра без проверки Свойство() — ошибка, если форму открыли без параметра
04
Отсутствие флажка «Вызов сервера» у общего модуля — клиент не видит экспортные процедуры модуля
05
Передача адреса временного хранилища между сеансами — хранилище живет ограниченное время, адрес становится недействительным

Проверка результата и отладка передачи параметров

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

Второй способ — временно вывести тип и значение параметра через Сообщить() на сервере: сообщения сервера доходят до клиента после завершения вызова. Если значение пришло пустым, хотя на клиенте было заполнено, чаще всего причина в несовпадении имен ключей структуры или в том, что параметр передан «по значению», а изменения на сервере ожидались на клиенте.

Контрольные точки

Как проверить результат

Значение параметра на сервере
Норма

Совпадает с переданным с клиента, тип соответствует ожидаемому

Тревожный признак

Пустое значение или другой тип — проверьте имена ключей структуры и сериализуемость типа

Количество серверных вызовов
Норма

Один вызов на логическую операцию

Тревожный признак

Вызовы в цикле — перенесите обработку на сервер целиком

Доступность процедуры с клиента
Норма

Вызов выполняется без ошибок

Тревожный признак

«Процедура не определена» — проверьте директиву &НаСервере и флажок «Вызов сервера»

Маршрут решения

Как выбрать способ передачи

Нужен быстрый расчет или чтение данных в текущей формеСерверная процедура формы, желательно &НаСервереБезКонтекста
Логика используется в нескольких формахОбщий модуль с флажками «Сервер» и «Вызов сервера»
Нужно передать данные в открываемую формуСтруктура параметров в ОткрытьФорму()
Операция занимает заметное времяФоновое задание, параметры — структурой, результат — через временное хранилище
Нужно передать файлСначала поместить файл во временное хранилище с клиента, на сервер передать адрес

Частые вопросы

Можно ли передать параметр по ссылке, чтобы сервер изменил его на клиенте?

Да, если параметр объявлен без ключевого слова Знач, изменения возвращаются клиенту. Но это работает только для сериализуемых типов и увеличивает объем передаваемых данных. Явно возвращать результат через Возврат функции — более предсказуемый подход.

Почему возникает ошибка «Ошибка передачи данных между клиентом и сервером»?

Почти всегда причина — попытка передать несериализуемый тип: объект базы данных (ДокументОбъект), запрос, элемент формы или структуру, внутри которой лежит такой объект. Проверьте состав передаваемых данных и замените объекты на ссылки.

Чем &НаСервере отличается от &НаСервереБезКонтекста при передаче параметров?

Процедура &НаСервере имеет доступ к данным формы, но при её вызове платформа сериализует весь контекст формы. &НаСервереБезКонтекста передает только явные параметры, поэтому вызов быстрее, но доступа к реквизитам формы внутри такой процедуры нет — всё нужное передавайте параметрами.

Как передать таблицу значений с клиента на сервер?

Таблица значений сериализуется напрямую, если типы колонок сериализуемы. Если данные находятся в реквизите формы типа ДанныеФормыКоллекция, в процедуре &НаСервере преобразуйте их через РеквизитФормыВЗначение(), а в процедуре без контекста соберите данные в массив структур на клиенте.

Можно ли вызвать серверную процедуру из тонкого или веб-клиента?

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

Как передать параметр, если форма открывается из другой формы и нужно вернуть результат?

Используйте ОткрытьФорму() с указанием владельца и обработайте результат в обработчике ОбработкаВыбора() формы-владельца, либо передайте ОписаниеОповещения — вызываемая форма выполнит оповещение с результатом через Закрыть(Результат).

Итог

Что важно запомнить

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