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

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

Как передать объект на сервер в 1С: рабочие способы и примеры кода

Как передать объект с клиента на сервер в 1С: сериализация, структуры, хранилище значения, временные таблицы. Рабочие примеры кода и типичные ошибки разработчика.

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

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

Ниже разобраны основные способы передачи данных с клиента на сервер: через структуры и массивы, через сериализацию в XML/JSON, через хранилище значения и через временное хранилище формы. Для каждого способа приведён рабочий код и указаны ограничения.

Что можно и что нельзя передавать между клиентом и сервером

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

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

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

Структура, массив, примитивыПередаются

Основной способ упаковки данных для серверного вызова

Ссылка на объектПередаётся

На сервере объект получают через Ссылка.ПолучитьОбъект()

ДокументОбъект, СправочникОбъектНе передаются

Вызов падает с ошибкой передачи данных

ТаблицаЗначенийУсловно

Передаётся в тонком/веб-клиенте, но надёжнее через сериализацию или реквизит формы

Передача данных через структуру — основной способ

Структура — стандартный контейнер для передачи набора реквизитов на сервер. На клиенте формируется структура с нужными полями, затем она передаётся параметром в экспортную процедуру серверного общего модуля с флагом «Сервер».

Пример клиентского кода:

&НаКлиенте

Процедура ЗаписатьДанные(Команда)

ПараметрыЗаписи = Новый Структура;

ПараметрыЗаписи.Вставить("Ссылка", Объект.Ссылка);

ПараметрыЗаписи.Вставить("Комментарий", Объект.Комментарий);

ПараметрыЗаписи.Вставить("Сумма", Объект.СуммаДокумента);

Результат = ЗаписатьДанныеНаСервере(ПараметрыЗаписи);

Если Результат.Успех Тогда

ПоказатьОповещениеПользователя("Данные записаны");

КонецЕсли;

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

Серверная часть размещается в общем модуле с установленными флагами «Сервер» и «Вызов сервера»:

Функция ЗаписатьДанныеНаСервере(ПараметрыЗаписи) Экспорт

Результат = Новый Структура("Успех, ОписаниеОшибки", Ложь, "");

Попытка

ДокОбъект = ПараметрыЗаписи.Ссылка.ПолучитьОбъект();

ДокОбъект.Комментарий = ПараметрыЗаписи.Комментарий;

ДокОбъект.СуммаДокумента = ПараметрыЗаписи.Сумма;

ДокОбъект.Записать();

Результат.Успех = Истина;

Исключение

Результат.ОписаниеОшибки = ОписаниеОшибки();

КонецПопытки;

Возврат Результат;

КонецФункции

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

Передача таблиц и сложных данных через сериализацию

Сериализация в XML через XDTO

Когда нужно передать таблицу значений, дерево или вложенные коллекции, структуры уже недостаточно. Платформа предоставляет сериализатор XDTO, который превращает таблицу значений в строку XML и обратно:

// Упаковка на клиенте

ЗаписьXML = Новый ЗаписьXML;

ЗаписьXML.УстановитьСтроку();

СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТаблицаДанных);

СтрокаXML = ЗаписьXML.Закрыть();

// Распаковка на сервере

ЧтениеXML = Новый ЧтениеXML;

ЧтениеXML.УстановитьСтроку(СтрокаXML);

ТаблицаДанных = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);

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

Сериализация в JSON

JSON удобен, когда данные дополнительно используются для обмена с внешними системами или веб-сервисами. Встроенные средства ЗаписьJSON/ЧтениеJSON работают с примитивами, структурами, массивами и соответствиями. Ссылки и специфические типы 1С в JSON напрямую не сериализуются — их нужно предварительно преобразовать в строки (например, строковое представление уникального идентификатора ссылки).

Способы упаковки данных

Структура

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

XML через XDTO

Таблицы значений, деревья, сложные коллекции. Сохраняет типы, но даёт объёмный текст

JSON

Обмен с внешними системами и веб-сервисами. Требует ручного преобразования ссылок и дат

Хранилище значения

Передача двоичных данных, картинок, произвольных объектов. Накладные расходы на сжатие

Передача через хранилище значения и временное хранилище

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

Для форм удобнее временное хранилище. Клиент помещает данные через ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификаторФормы), получает адрес (строку) и передаёт на сервер только этот адрес. Сервер забирает данные через ПолучитьИзВременногоХранилища(Адрес). Так не гоняется большой объём данных в параметрах вызова — передаётся лишь короткая строка-адрес.

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

Порядок передачи таблицы с клиента на сервер
  1. 1
    На клиенте сформируйте таблицу значений или структуру с данными, заменив объекты на ссылки
  2. 2
    Упакуйте данные: структура для простых случаев, XML/JSON или хранилище значения для сложных
  3. 3
    Вызовите экспортную функцию серверного общего модуля с флагами «Сервер» и «Вызов сервера»
  4. 4
    На сервере распакуйте данные и при необходимости получите объекты по ссылкам
  5. 5
    Верните на клиент структуру с признаком успеха и описанием ошибки
  6. 6
    Проверьте результат на клиенте и покажите пользователю итог операции

Передача данных через реквизиты формы

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

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

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

Частые ошибки и как их диагностировать

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

Вторая типичная проблема — мутабельность параметров. Значения, переданные в серверный вызов, копируются: изменения параметра на сервере не отражаются на клиенте. Если нужен результат — возвращайте его явно через Возврат, а не рассчитывайте, что переданная структура изменится «по ссылке».

Третья группа ошибок связана с производительностью: множество мелких серверных вызовов в цикле. Каждый вызов — это сетевой обмен. Собирайте данные в пакет (массив структур) и обрабатывайте одним вызовом на сервере.

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

Как проверить, что передача прошла корректно

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

Для отладки используйте отладчик с точкой останова в серверной процедуре: в конфигураторе включите отладку по протоколу HTTP или TCP (в зависимости от режима) и убедитесь, что в параметрах приходят именно те данные, которые сформировал клиент. Если параметр приходит пустым — проблема на клиенте, если данные есть, но обработка падает — в серверной логике.

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

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

Параметры в точке останова на сервере
Норма

Все поля заполнены ожидаемыми значениями и типами

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

Поля пустые или тип значения отличается от ожидаемого

Возвращаемое значение на клиенте
Норма

Структура с Успех = Истина и заполненным результатом

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

Неопределено или описание ошибки

Записанные данные в базе
Норма

Объект изменён, количество записей совпадает с отправленным

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

Часть данных потерялась или не записалась

Время выполнения
Норма

Один серверный вызов на пакет данных

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

Вызовы идут в цикле, заметные задержки интерфейса

FAQ

Можно ли передать ДокументОбъект с клиента на сервер напрямую?

Нет. Объекты прикладных типов не сериализуются и не передаются между контекстами. Передавайте ссылку, а на сервере получайте объект через Ссылка.ПолучитьОбъект(). Изменённые реквизиты передавайте отдельно в структуре.

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

В параметрах вызова или в возвращаемом значении есть непередаваемый тип: объект документа, запрос, COM-объект или структура с таким объектом внутри. Переберите состав передаваемых данных и замените объекты на ссылки или примитивы.

Чем структура лучше сериализации в XML?

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

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

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

Изменения структуры на сервере видны на клиенте?

Нет. Параметры серверного вызова передаются по значению — клиент и сервер работают с разными копиями. Результат нужно возвращать явно через Возврат функции и обрабатывать на клиенте.

Как сократить нагрузку при передаче больших объёмов данных?

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

Итог

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

Напрямую объекты 1С между клиентом и сервером не передаются. Упаковывайте данные в структуры, XML/JSON, хранилище значения или временное хранилище, передавайте ссылки вместо объектов, возвращайте результат явно и объединяйте вызовы в пакеты.