Разработка и Конфигурация · 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 напрямую не сериализуются — их нужно предварительно преобразовать в строки (например, строковое представление уникального идентификатора ссылки).
Способы упаковки данных
Простые наборы реквизитов. Быстро и наглядно, но не подходит для таблиц и глубокой вложенности
Таблицы значений, деревья, сложные коллекции. Сохраняет типы, но даёт объёмный текст
Обмен с внешними системами и веб-сервисами. Требует ручного преобразования ссылок и дат
Передача двоичных данных, картинок, произвольных объектов. Накладные расходы на сжатие
Передача через хранилище значения и временное хранилище
Хранилище значения (Новый ХранилищеЗначения(Данные)) упаковывает произвольное значение с возможностью сжатия. Это рабочий вариант для передачи двоичных данных, картинок и объектов, которые нельзя сериализовать напрямую. На сервере данные извлекаются методом Получить().
Для форм удобнее временное хранилище. Клиент помещает данные через ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификаторФормы), получает адрес (строку) и передаёт на сервер только этот адрес. Сервер забирает данные через ПолучитьИзВременногоХранилища(Адрес). Так не гоняется большой объём данных в параметрах вызова — передаётся лишь короткая строка-адрес.
Важно: время жизни временного хранилища ограничено. Если привязать хранилище к уникальному идентификатору формы, данные живут, пока открыта форма. Без привязки данные удаляются после очередного обращения к серверу или по таймауту — рассчитывать на долгое хранение нельзя.
- 1На клиенте сформируйте таблицу значений или структуру с данными, заменив объекты на ссылки
- 2Упакуйте данные: структура для простых случаев, XML/JSON или хранилище значения для сложных
- 3Вызовите экспортную функцию серверного общего модуля с флагами «Сервер» и «Вызов сервера»
- 4На сервере распакуйте данные и при необходимости получите объекты по ссылкам
- 5Верните на клиент структуру с признаком успеха и описанием ошибки
- 6Проверьте результат на клиенте и покажите пользователю итог операции
Передача данных через реквизиты формы
Если данные отображаются в управляемой форме, часто вообще не нужно ничего передавать: реквизиты формы сами синхронизируются между клиентом и сервером при серверном вызове контекста формы. Табличная часть формы (ДанныеФормыКоллекция) доступна и в клиентском, и в серверном контексте — платформа сама переносит её содержимое.
Для работы с таблицей значений на сервере используйте преобразование: РеквизитФормыВЗначение("ИмяРеквизита") превращает реквизит формы в таблицу значений, а ЗначениеВРеквизитФормы() — обратно. Это стандартный приём для обработки табличных данных в серверных процедурах формы с директивой &НаСервере.
Учтите, что вызовы &НаСервере в контексте формы переносят весь контекст формы, что при больших таблицах даёт заметный трафик. Для тяжёлых операций предпочтительнее выносить логику в общий модуль без контекста формы и передавать только нужные данные.
Частые ошибки и как их диагностировать
Самая распространённая ошибка — попытка передать объект вместо ссылки. Сообщение «Ошибка передачи данных между клиентом и сервером» почти всегда означает, что в параметрах или внутри структуры затесался непередаваемый тип. Проверяйте вложенные коллекции: структура может выглядеть безобидно, но содержать в глубине объект.
Вторая типичная проблема — мутабельность параметров. Значения, переданные в серверный вызов, копируются: изменения параметра на сервере не отражаются на клиенте. Если нужен результат — возвращайте его явно через Возврат, а не рассчитывайте, что переданная структура изменится «по ссылке».
Третья группа ошибок связана с производительностью: множество мелких серверных вызовов в цикле. Каждый вызов — это сетевой обмен. Собирайте данные в пакет (массив структур) и обрабатывайте одним вызовом на сервере.
Перед отладкой передачи данных полезно временно вывести состав структуры через Сообщить() на клиенте: переберите ключи и типы значений. Это быстрее, чем искать непередаваемый тип по тексту ошибки, особенно при вложенных структурах.
Как проверить, что передача прошла корректно
Минимальная проверка — вернуть с сервера структуру с признаком успеха и диагностической информацией: количеством обработанных строк, ссылкой на созданный объект, текстом ошибки. На клиенте сравните ожидаемое и фактическое количество записей.
Для отладки используйте отладчик с точкой останова в серверной процедуре: в конфигураторе включите отладку по протоколу HTTP или TCP (в зависимости от режима) и убедитесь, что в параметрах приходят именно те данные, которые сформировал клиент. Если параметр приходит пустым — проблема на клиенте, если данные есть, но обработка падает — в серверной логике.
Как проверить результат
Все поля заполнены ожидаемыми значениями и типами
Поля пустые или тип значения отличается от ожидаемого
Структура с Успех = Истина и заполненным результатом
Неопределено или описание ошибки
Объект изменён, количество записей совпадает с отправленным
Часть данных потерялась или не записалась
Один серверный вызов на пакет данных
Вызовы идут в цикле, заметные задержки интерфейса
FAQ
Можно ли передать ДокументОбъект с клиента на сервер напрямую?
Нет. Объекты прикладных типов не сериализуются и не передаются между контекстами. Передавайте ссылку, а на сервере получайте объект через Ссылка.ПолучитьОбъект(). Изменённые реквизиты передавайте отдельно в структуре.
Почему возникает ошибка «Ошибка передачи данных между клиентом и сервером»?
В параметрах вызова или в возвращаемом значении есть непередаваемый тип: объект документа, запрос, COM-объект или структура с таким объектом внутри. Переберите состав передаваемых данных и замените объекты на ссылки или примитивы.
Чем структура лучше сериализации в XML?
Структура проще, быстрее и нагляднее для плоских наборов реквизитов. Сериализация нужна для таблиц значений, деревьев и вложенных коллекций, которые структурой не описать. Для простых случаев сериализация — избыточное усложнение.
Как передать картинку или файл с клиента на сервер?
Поместите файл во временное хранилище на клиенте через НачатьПомещениеФайла или ПоместитьВоВременноеХранилище, передайте на сервер полученный адрес и извлеките двоичные данные через ПолучитьИзВременногоХранилища. Альтернатива — хранилище значения с двоичными данными.
Изменения структуры на сервере видны на клиенте?
Нет. Параметры серверного вызова передаются по значению — клиент и сервер работают с разными копиями. Результат нужно возвращать явно через Возврат функции и обрабатывать на клиенте.
Как сократить нагрузку при передаче больших объёмов данных?
Группируйте данные в пакеты и вызывайте сервер один раз вместо вызовов в цикле. Для больших таблиц используйте временное хранилище, чтобы не передавать данные в параметрах. Сжатие в ХранилищеЗначения уменьшает объём передаваемого текста XML.
Что важно запомнить
Напрямую объекты 1С между клиентом и сервером не передаются. Упаковывайте данные в структуры, XML/JSON, хранилище значения или временное хранилище, передавайте ссылки вместо объектов, возвращайте результат явно и объединяйте вызовы в пакеты.