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