Как исправить ошибку «Значение недопустимого типа» при передаче данных между клиентом и сервером в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в управляемом приложении 1С программисты часто сталкиваются с ошибкой передачи данных между контекстами клиента и сервера: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа». Разберем подробнее, почему возникает эта проблема, какие типы данных нельзя передавать напрямую и как правильно организовать получение и передачу списков документов и табличных данных на форме.

Причина возникновения ошибки

При выполнении контекстного вызова сервера платформа 1С производит XDTO-сериализацию всех параметров, передаваемых между клиентом и сервером. Если среди параметров или в возвращаемом значении функции оказывается объект, который не поддерживает автоматическую сериализацию, платформа генерирует исключение.

Главная причина заключается в попытке передать серверный объект на клиентскую сторону. К объектам, недопустимым для прямой передачи между клиентом и сервером, относятся:

  1. Серверные коллекции и таблицы: ТаблицаЗначений, ДеревоЗначений, СтрокаТаблицыЗначений, Запрос, РезультатЗапроса.
  2. Объекты модификации данных базы: СправочникОбъект, ДокументОбъект и аналогичные типы. На клиенте могут существовать исключительно ссылки, например ДокументСсылка или СправочникСсылка.
  3. Элементы интерфейса: УправляемаяФорма и ее элементы.

Решение 1. Использование универсальной коллекции «СписокЗначений» или «Массив»

Если задача заключается в том, чтобы получить с сервера и передать на клиент список ссылок (например, массив или список документов tertentu), вместо ТаблицаЗначений следует использовать сериализуемые типы: СписокЗначений или Массив.

Рассмотрим пример функции на сервере, которая формирует и возвращает СписокЗначений со ссылками на документы:


&НаСервере
Функция ПолучитьСписокДокументовНаСервере()
    
    СписокДокументов = Новый СписокЗначений;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   СборкаЗапасов.Ссылка КАК Ссылка
        |ИЗ
        |   Документ.СборкаЗапасов КАК СборкаЗапасов";
        
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        СписокДокументов.Добавить(Выборка.Ссылка);
    КонецЦикла;
    
    Возвращать СписокДокументов;
    
КонецФункции

Поскольку СписокЗначений состоит из ссылок типа ДокументСсылка, он успешно передается на клиент без вызова ошибки.

Решение 2. Преобразование таблицы значений в данные формы

Если табличные данные необходимо отобразить в интерфейсе управляемой формы, прямое использование типа ТаблицаЗначений на клиенте невозможно. Для этого на форме создается реквизит с типом ТаблицаЗначений, который на клиенте представлен объектом ДанныеФормыКоллекция.

Преобразование выполняется специализированными процедурами платформы:

  1. Передача данных на форму: вызов процедуры ЗначениеВДанныеФормы(ТаблицаИсточника, РеквизитФормы) на сервере.
  2. Обратное считывание с формы на сервере: вызов функции ДанныеФормыВЗначение(РеквизитФормы, Тип("ТаблицаЗначений")).

Посмотрим на пример заполнения реквизита формы на сервере:


&НаСервере
Процедура ЗаполнитьТаблицуНаФормеСервер()
    
    ВременнаяТЗ = Новый ТаблицаЗначений;
    ВременнаяТЗ.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка.СборкаЗапасов"));
    
    // Заполнение таблицы значений нужными данными
    // ...
    
    // Конвертация в реквизит формы
    ЗначениеВДанныеФормы(ВременнаяТЗ, Объект.СборкаЗапасовТаблица);
    
КонецПроцедуры

Решение 3. Использование массива структур

Когда требуется передать сложную табличную структуру на клиент, но привязывать её к реквизитам формы не нужно, оптимальным решением выступает формирование массива структур. Объекты Массив и Структура свободно передаются между клиентом и сервером, если их элементы содержат базовые типы или ссылки.


&НаСервере
Функция ПолучитьТабличныеДанныеНаСервере()
    
    РезультатМассив = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Т.Ссылка КАК Ссылка,
        |   Т.Дата КАК Дата
        |ИЗ
        |   Документ.СборкаЗапасов КАК Т";
        
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Стр = Новый Структура;
        Стр.Вставить("Ссылка", Выборка.Ссылка);
        Стр.Вставить("Дата", Выборка.Дата);
        РезультатМассив.Добавить(Стр);
    КонецЦикла;
    
    Возвращать РезультатМассив;
    
КонецФункции

Решение 4. Передача через временное хранилище

Если ТаблицаЗначений или иной серверный объект формируется в одном серверном контексте и требуется исключительно для последующей обработки в другом серверном вызове без необходимости разбора на клиенте, используйте временное хранилище:

  1. На сервере помещаем объект во временное хранилище с помощью ПоместитьВоВременноеХранилище() и получаем строковый адрес.
  2. Возвращаем адрес хранилища (тип Строка) на клиент.
  3. При следующем вызове сервера передаем адрес обратно и извлекаем данные вызовом ПолучитьИзВременногоХранилища().

Таким образом, для исключения ошибки «Значение недопустимого типа» всегда контролируйте типы данных, пересекающие границу клиент-серверного взаимодействия, и используйте СписокЗначений, Массив, Структура или реквизиты формы.

← На главную