Разработка и Конфигурация · 11 мин
Какие данные можно передавать между клиентом и сервером в 1С
Какие данные 1С можно передавать между клиентом и сервером: сериализуемые типы, ограничения, мутабельные значения, передача файлов и типичные ошибки разработчиков.
В клиент-серверной архитектуре 1С:Предприятие любой вызов серверной процедуры из клиентского кода означает передачу данных через границу процессов, а чаще — через сеть. Платформа не передаёт объекты «как есть»: она сериализует значения в промежуточное представление на стороне отправителя и восстанавливает их на стороне получателя. Из-за этого передавать можно далеко не всё, а часть типов ведёт себя неочевидно.
Ошибки вида «Ошибка передачи данных между клиентом и сервером» или «Значение недопустимого типа» возникают именно тогда, когда разработчик пытается передать несериализуемый объект — например, ссылку на объект COM, таблицу значений в неподходящем контексте или объект, привязанный к конкретному сеансу. Понимание правил сериализации позволяет заранее проектировать интерфейсы серверных процедур так, чтобы обмен был быстрым и предсказуемым.
Материал описывает, какие категории данных свободно перемещаются между клиентом и сервером, какие требуют преобразования, а какие запрещены, и как выстроить обмен так, чтобы не терять производительность и не ловить ошибки в рабочей базе.
Как платформа передаёт данные между клиентом и сервером
При вызове серверной процедуры платформа выполняет маршалинг: каждый параметр преобразуется в потоковое представление, передаётся на сервер, там восстанавливается, а после выполнения процедуры результат и изменённые параметры проходят обратный путь. Это справедливо и для тонкого клиента, и для веб-клиента, и для файлового режима с разделённым контекстом.
Из механики следуют два практических следствия. Первое: каждый вызов сервера — это сетевой обмен, поэтому десять мелких вызовов в цикле почти всегда медленнее одного вызова с пакетом данных. Второе: на сервере вы получаете копию переданных данных, а не тот же объект. Изменения копии на сервере не отразятся на клиенте, если значение не помечено как возвращаемое (Знач) или не возвращено явно.
Отдельный случай — вызовы с клиента на сервер в управляемых формах. Здесь платформа дополнительно управляет временем жизни временных хранилищ и реквизитов формы, что открывает способ передавать большие данные без копирования через параметры.
Примитивные и простые типы: что передаётся без ограничений
Базовые типы передаются в обе стороны без подготовки: строка, число, булево, дата, неопределено, NULL, тип, уникальный идентификатор. Они сериализуются напрямую и не создают накладных расходов сверх размера самого значения.
К этой же группе относятся ссылки на объекты базы данных — справочники, документы, планы счетов и другие. Ссылка передаётся как лёгкий идентификатор: сам объект из базы не выгружается. Однако важно понимать: если на сервере вы обратитесь к реквизитам ссылки, платформа выполнит запрос к базе. Передача ссылки дёшева, а разыменование — нет.
Также без ограничений передаются стандартные коллекции, если их элементы сериализуемы:
- Массив и фиксированный массив;
- Структура и фиксированная структура;
- Соответствие и фиксированное соответствие;
- СписокЗначений;
- ТаблицаЗначений и дерево значений (с ограничениями по контексту формы).
Мутабельные значения и директивы переноса
Часть типов платформа относит к мутабельным (изменяемым) — прежде всего таблица значений. Для них действует особое правило при вызове серверных процедур с модификатором &НаСервере из контекста формы: по умолчанию такие значения могут быть запрещены к передаче, и компилятор или платформа сообщит об этом.
Решение — явно указать направление переноса в объявлении параметра серверной процедуры:
&НаСервере
Процедура ОбработатьНаСервере(Знач ТаблицаДанных)
// ТаблицаДанных — сериализованная копия
КонецПроцедуры
Модификатор Знач фиксирует, что значение передаётся копией и не должно возвращаться обратно. Если результат обработки нужен на клиенте, верните его через Возврат или передайте параметр без Знач — тогда платформа перенесёт изменённое значение обратно, но это удвоит трафик по данному параметру.
Способы вернуть результат с сервера
Оптимально для одного результата; передача в одну сторону, минимальный трафик.
Подходит, когда нужно вернуть несколько изменённых коллекций; цена — обратная сериализация каждого параметра.
Лучший вариант для больших данных: через параметры идёт только адрес строкой.
Передача больших данных: временное хранилище и двоичные данные
Когда объём данных велик — файл, отчёт, большая таблица — передавать его параметрами нерационально: значение будет сериализовано дважды (туда и обратно) и займёт память на обеих сторонах. Для таких сценариев предназначено временное хранилище.
Типовая схема: на клиенте файл помещается в хранилище методом НачатьПомещениеФайла (или значение помещается функцией ПоместитьВоВременноеХранилище), на сервер передаётся только адрес — строка. Серверная процедура извлекает данные по адресу через ПолучитьИзВременногоХранилища, обрабатывает и при необходимости помещает результат в хранилище, возвращая новый адрес.
Двоичные данные (ДвоичныеДанные) и хранилище значения (ХранилищеЗначения) сериализуемы и могут передаваться напрямую, но для объектов больше нескольких мегабайт предпочтителен обмен через хранилище. ХранилищеЗначения дополнительно сжимает содержимое, что снижает трафик.
- 1На клиенте вызовите НачатьПомещениеФайла с указанием уникального идентификатора формы — тогда хранилище будет жить, пока жива форма.
- 2В обработчике завершения получите адрес хранилища и передайте его в серверную процедуру строкой.
- 3На сервере извлеките двоичные данные через ПолучитьИзВременногоХранилища(Адрес).
- 4Обработайте данные; результат, если он крупный, поместите в хранилище и верните адрес.
- 5На клиенте заберите результат по адресу и при необходимости удалите данные из хранилища через УдалитьИзВременногоХранилища.
Что передавать нельзя или нельзя без подготовки
Категория несериализуемых объектов — главный источник ошибок обмена. Не передаются между клиентом и сервером:
- элементы управляемой формы, сама форма, данные формы в виде объекта;
- объекты, привязанные к выполнению: Запрос с установленными параметрами в части контекстов, ПостроительОтчета, объекты СКД в ряде режимов;
- COM-объекты, OLE, внешние компоненты — они существуют только в своём процессе;
- объекты метаданных как рабочие экземпляры (передавать можно имя метаданных строкой);
- фоновые задания, объекты транзакций, соединения с внешними источниками.
Общий принцип проверки прост: если объект имеет смысл только внутри конкретного процесса или сеанса, он не переживёт сериализацию. Вместо самого объекта передавайте данные, необходимые для его восстановления: имя метаданных, настройки в виде структуры, адрес хранилища.
Отдельно упомянем картинки и макеты: Картинка сериализуема, но для регулярного обмена изображениями правильнее передавать двоичные данные или адрес хранилища — это предсказуемее по памяти.
Проектирование обмена: как снизить трафик и число вызовов
Главная метрика качества клиент-серверного кода — количество вызовов сервера и объём передаваемых данных. Практические правила, которые дают эффект без усложнения архитектуры:
- Объединяйте связанные параметры в одну структуру и делайте один вызов вместо серии мелких;
- Передавайте на клиент только те поля, которые реально отображаются, а не всю таблицу целиком;
- Используйте серверные вызовы без контекста формы (в общих модулях с признаком «Вызов сервера»), когда данные формы не нужны — так обмен легче;
- Для повторно используемых данных применяйте повторное использование возвращаемых значений (кэш на время сеанса или вызова);
- Не передавайте с сервера данные, которые клиент не использует: каждое поле структуры — это байты в сети.
Проверить результат оптимизации можно штатными средствами: замер производительности в конфигураторе покажет количество и длительность серверных вызовов, а технологический журнал — фактические объёмы передаваемых данных. Ориентир простой: интерактивное действие пользователя не должно порождать десятки вызовов сервера.
Что важно запомнить
Передавайте сериализуемые типы: примитивы, ссылки, коллекции, двоичные данные. Большие объёмы — через временное хранилище по адресу. Несериализуемые объекты заменяйте данными для их восстановления. Минимизируйте число вызовов и объём каждого ответа.
Частые вопросы о передаче данных между клиентом и сервером
Можно ли передать на сервер таблицу значений, заполненную на клиенте?
Да, таблица значений сериализуема. В параметре серверной процедуры укажите модификатор Знач, чтобы передать копию в одну сторону, либо объявите параметр без Знач, если изменённая таблица должна вернуться на клиент. Учитывайте, что при большом объёме выгоднее поместить таблицу во временное хранилище и передать только адрес.
Почему возникает ошибка «Значение недопустимого типа» при вызове сервера?
Почти всегда причина — попытка передать несериализуемый объект: элемент формы, запрос, COM-объект или коллекцию, внутри которой лежит такой объект. Проверьте вложенные структуры и соответствия: ошибка возникает по всей коллекции целиком, даже если проблемный элемент один.
Чем отличается передача ссылки от передачи объекта?
Ссылка — лёгкий идентификатор, передаётся быстро и не выгружает данные из базы. Объект (например, СправочникОбъект) тяжелее, а в ряде контекстов вообще не подлежит передаче. Практическое правило: обменивайтесь ссылками, а выборку реквизитов делайте запросом там, где данные нужны.
Как передать картинку или файл с сервера на клиент?
Надёжнее всего поместить двоичные данные во временное хранилище на сервере и вернуть клиенту адрес. Клиент получает данные по адресу через ПолучитьИзВременногоХранилища. Прямая передача типа Картинка тоже возможна, но при больших размерах хранилище предсказуемее по памяти и трафику.
Что быстрее: вернуть структуру с данными или записать данные в реквизиты формы на сервере?
Если серверная процедура выполняется в контексте формы, запись в реквизиты формы не требует отдельной сериализации результата — данные уйдут на клиент вместе с состоянием формы. Для вызовов вне контекста формы остаётся только возврат значения. Выбор зависит от того, где логичнее хранить результат.
Передаются ли данные между клиентом и сервером в файловом режиме?
Да, разделение контекстов сохраняется и в файловом режиме: серверные процедуры выполняются в отдельном контексте, и правила сериализации действуют в полном объёме. Поэтому код, корректный для клиент-серверного варианта, будет работать и в файловом, а вот обратное при нарушении правил — не гарантировано.