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