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

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

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

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

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

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

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

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

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

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

Отдельный случай — вызовы с клиента на сервер в управляемых формах. Здесь платформа дополнительно управляет временем жизни временных хранилищ и реквизитов формы, что открывает способ передавать большие данные без копирования через параметры.

Примитивные и простые типы: что передаётся без ограничений

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

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

Также без ограничений передаются стандартные коллекции, если их элементы сериализуемы:

  • Массив и фиксированный массив;
  • Структура и фиксированная структура;
  • Соответствие и фиксированное соответствие;
  • СписокЗначений;
  • ТаблицаЗначений и дерево значений (с ограничениями по контексту формы).

Мутабельные значения и директивы переноса

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

Решение — явно указать направление переноса в объявлении параметра серверной процедуры:

&НаСервере

Процедура ОбработатьНаСервере(Знач ТаблицаДанных)

// ТаблицаДанных — сериализованная копия

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

Модификатор Знач фиксирует, что значение передаётся копией и не должно возвращаться обратно. Если результат обработки нужен на клиенте, верните его через Возврат или передайте параметр без Знач — тогда платформа перенесёт изменённое значение обратно, но это удвоит трафик по данному параметру.

Способы вернуть результат с сервера

Возврат функции

Оптимально для одного результата; передача в одну сторону, минимальный трафик.

Параметр без Знач

Подходит, когда нужно вернуть несколько изменённых коллекций; цена — обратная сериализация каждого параметра.

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

Лучший вариант для больших данных: через параметры идёт только адрес строкой.

Передача больших данных: временное хранилище и двоичные данные

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

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

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

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

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

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

  • элементы управляемой формы, сама форма, данные формы в виде объекта;
  • объекты, привязанные к выполнению: Запрос с установленными параметрами в части контекстов, ПостроительОтчета, объекты СКД в ряде режимов;
  • COM-объекты, OLE, внешние компоненты — они существуют только в своём процессе;
  • объекты метаданных как рабочие экземпляры (передавать можно имя метаданных строкой);
  • фоновые задания, объекты транзакций, соединения с внешними источниками.

Общий принцип проверки прост: если объект имеет смысл только внутри конкретного процесса или сеанса, он не переживёт сериализацию. Вместо самого объекта передавайте данные, необходимые для его восстановления: имя метаданных, настройки в виде структуры, адрес хранилища.

Отдельно упомянем картинки и макеты: Картинка сериализуема, но для регулярного обмена изображениями правильнее передавать двоичные данные или адрес хранилища — это предсказуемее по памяти.

Проектирование обмена: как снизить трафик и число вызовов

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

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

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

Итог

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

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

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

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

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

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

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

Чем отличается передача ссылки от передачи объекта?

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

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

Надёжнее всего поместить двоичные данные во временное хранилище на сервере и вернуть клиенту адрес. Клиент получает данные по адресу через ПолучитьИзВременногоХранилища. Прямая передача типа Картинка тоже возможна, но при больших размерах хранилище предсказуемее по памяти и трафику.

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

Если серверная процедура выполняется в контексте формы, запись в реквизиты формы не требует отдельной сериализации результата — данные уйдут на клиент вместе с состоянием формы. Для вызовов вне контекста формы остаётся только возврат значения. Выбор зависит от того, где логичнее хранить результат.

Передаются ли данные между клиентом и сервером в файловом режиме?

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