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

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

1С: что можно передать на сервер — типы данных и правила передачи

Какие данные можно передать с клиента на сервер в 1С: сериализуемые типы, ограничения, мутабельные значения, ДанныеФормы, примеры кода и типичные ошибки разработчиков.

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

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

Ниже разобрано, какие типы проходят границу клиент–сервер без ограничений, какие требуют обёрток, как работать с ДанныеФормы и мутабельными значениями, и как проверить, что передача выполняется корректно и не перегружает канал.

Как устроена передача данных между клиентом и сервером

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

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

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

Примитивные типы и универсальные коллекции

Без ограничений передаются примитивные типы: Строка, Число, Дата, Булево, Неопределено, Null, Тип, УникальныйИдентификатор, а также ДвоичныеДанные. Двоичные данные — стандартный способ передать файл на сервер: на клиенте файл помещается во временное хранилище или читается в двоичные данные, затем передаётся.

Из коллекций сериализуются Массив, Структура, Соответствие, СписокЗначений, ТаблицаЗначений, ДеревоЗначений, ФиксированныйМассив и ФиксированнаяСтруктура. Вложенность разрешена: структура может содержать массивы структур и так далее, при условии что все вложенные значения тоже сериализуемы.

Практический приём — передавать на сервер одну структуру с именованными полями вместо длинного списка параметров. Это упрощает сопровождение: добавление нового поля не меняет сигнатуру процедуры.

bsl
&НаКлиенте
Процедура ОтправитьНаСервер(Команда)
	ПараметрыРасчета = Новый Структура;
	ПараметрыРасчета.Вставить("Организация", Организация);
	ПараметрыРасчета.Вставить("Период", Период);
	ПараметрыРасчета.Вставить("СписокНоменклатуры", СписокНоменклатуры.ВыгрузитьЗначения());
	Результат = РассчитатьНаСервере(ПараметрыРасчета);
КонецПроцедуры

&НаСервереБезКонтекста
Функция РассчитатьНаСервере(ПараметрыРасчета)
	// ПараметрыРасчета — обычная сериализуемая структура
	Возврат ВыполнитьРасчет(ПараметрыРасчета);
КонецФункции

Ссылки, объекты и данные информационной базы

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

Объекты типа ДокументОбъект или СправочникОбъект между клиентом и сервером напрямую не передаются — они существуют только в серверном контексте. Если нужно перенести набор изменённых реквизитов, соберите их в структуру или таблицу значений и передайте её.

Запросы и построители отчётов также не сериализуются. На сервер передают не объект запроса, а параметры для него: отборы, периоды, списки значений — а сам запрос конструируется и выполняется в серверном коде.

Работа с ДанныеФормы и мутабельными значениями

Реквизиты управляемой формы существуют в специальном формате — ДанныеФормыСтруктура, ДанныеФормыКоллекция и другие. Эти типы привязаны к форме и не сериализуются напрямую. Для передачи на сервер их нужно преобразовать: например, таблицу формы выгрузить через Выгрузить() в таблицу значений, а основной реквизит преобразовать методом РеквизитФормыВЗначение() — но последний работает только в серверном контексте формы.

Для передачи мутабельных (изменяемых на сервере) коллекций между вызовами платформа требует обёртку: типы ТаблицаЗначений и ДеревоЗначений, хранимые в реквизитах формы, должны иметь признак использования. На практике это означает: если серверная процедура должна вернуть изменённую таблицу, передайте её как параметр и верните обратно, либо храните её как реквизит формы типа «ТаблицаЗначений».

Типичный сценарий: клиент вызывает серверную процедуру формы &НаСервере, внутри которой доступен весь контекст формы. В этом случае отдельная передача реквизитов не нужна — серверный вызов формы автоматически переносит её данные. А вот вызов серверного общего модуля (&НаСервереБезКонтекста в форме или прямой вызов) контекст формы не получает — всё нужно передавать явно.

Куда выносить серверную логику

&НаСервере в модуле формы

Подходит, когда нужны реквизиты и элементы формы. Контекст формы передаётся автоматически, но вызов дороже из-за объёма данных формы.

Серверный общий модуль

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

&НаСервереБезКонтекста в форме

Компромисс: код физически в форме, но контекст не передаётся. Удобно для обработчиков, которым нужны лишь несколько параметров.

Что передать нельзя и как это обойти

Не сериализуются и не передаются на сервер: элементы управления формы, объекты ТекстовыйДокумент и ТабличныйДокумент в ряде контекстов, COM-объекты и объекты внешних компонент, открытые файловые потоки, Запрос, ПостроительЗапроса, объекты типа ХранилищеЗначения вне базы, а также любые объекты, созданные средствами ОС на клиенте.

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

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

Производительность и объём передаваемых данных

Главный фактор стоимости вызова — объём сериализуемых данных. Передача таблицы значений на десятки тысяч строк в каждом вызове способна сделать форму неюзабельной даже в локальной сети. Оценивайте: если данные нужны только серверу, пусть он сам их прочитает из базы; если нужны клиенту — передавайте один раз и кэшируйте в реквизитах формы.

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

Типичные ошибки
01
Передача элемента формы или ТабличногоПоля на сервер — ошибка сериализации; передавать нужно данные, а не элементы управления
02
Цикл с серверным вызовом на каждой итерации — сотни сетевых обращений; правильно собрать массив и вызвать сервер один раз
03
Передача ДанныеФормыКоллекция в общий модуль — тип не сериализуется; сначала Выгрузить() в таблицу значений
04
Возврат из сервера огромной таблицы, из которой клиент читает два поля — лишний трафик; верните только нужное
05
Забытое Неопределено вместо адреса хранилища при асинхронном помещении файла — сервер получает пустые данные

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

Проверка начинается с типов: убедитесь, что каждый параметр и возвращаемое значение относятся к сериализуемым типам. Сомнительный объект можно проверить попыткой сериализации через ЗначениеВСтрокуВнутр() — если значение не сериализуется, метод выдаст ошибку ещё на этапе отладки.

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

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

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

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

Типы параметров
Норма

Примитивы, структуры, массивы, ссылки, таблицы значений

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

Элементы формы, COM-объекты, Запрос, ДанныеФормы без преобразования

Содержимое на сервере
Норма

Количество строк и значения совпадают с отправленными клиентом

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

Пустые коллекции, Неопределено вместо значений

Время вызова
Норма

Десятки–сотни миллисекунд для типовой операции

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

Секунды при простой серверной логике — признак избыточного объёма

Временное хранилище
Норма

Адрес возвращает данные, хранилище очищается после использования

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

ПолучитьИзВременногоХранилища возвращает Неопределено, память сеанса растёт

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

Итог

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

На сервер проходят только сериализуемые типы: примитивы, коллекции, ссылки и таблицы значений. Контекстные объекты клиента не передаются — их заменяют адресом временного хранилища, ссылкой или структурой с данными. Минимальный объём и минимум вызовов — основа быстрой клиент-серверной работы.

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

Да, ТаблицаЗначений сериализуется и передаётся в обе стороны. Если таблица является реквизитом формы, в общий серверный модуль её передают после Выгрузить(). Следите за объёмом: большие таблицы разумнее формировать и обрабатывать целиком на сервере.

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

Чаще всего среди параметров оказался несериализуемый тип: элемент формы, ДанныеФормыКоллекция, объект запроса или COM-объект. Проверьте тип каждого параметра через ТипЗнч() и замените проблемные значения структурами, ссылками или адресами временного хранилища.

Как передать картинку или файл на сервер?

Через временное хранилище: клиент помещает файл и получает адрес, адрес передаётся строкой на сервер, сервер забирает двоичные данные методом ПолучитьИзВременногоХранилища. Альтернатива для небольших данных — прямая передача ДвоичныеДанные параметром.

Передаётся ли контекст формы в серверный общий модуль?

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

Что выгоднее: передать ссылку или структуру с реквизитами?

Если серверу нужны актуальные данные из базы — передавайте ссылку, это дешевле. Структуру с реквизитами используют, когда данные изменены на клиенте и ещё не записаны, либо когда объект вообще не хранится в базе.

Можно ли вернуть с сервера несколько значений одним вызовом?

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