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