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

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

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

Причина возникновения ошибки: Механизм XDTO-сериализации

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

Ошибка «Отсутствует отображение для типа» означает, что в составе передаваемых данных оказался объект, тип которого не поддерживается в целевом контексте или не может быть описан схемой XDTO. Чаще всего это случается с объектами, которые существуют только на сервере, но «случайно» пытаются вернуться на клиент. Для лучшего понимания работы контекстов исполнения пригодится публикация по управлению местом выполнения кода в управляемых формах.

Основные типы-нарушители:

  1. ТаблицаЗначений и ДеревоЗначений — эти объекты физически не могут существовать на тонком клиенте.
  2. ОписаниеОповещения — объект, содержащий ссылку на клиентскую процедуру, который сервер не может обработать или передать обратно.
  3. ХранилищеЗначения — требует специальной обработки при передаче.
  4. Запрос, РезультатЗапроса, ВыборкаИзРезультатаЗапроса — инструменты базы данных, недоступные на стороне клиента.

Сценарий 1: Изменение структуры на сервере

Рассмотрим классическую ситуацию из практики. Программист передает с клиента на сервер структуру с параметрами. Внутри серверной процедуры в эту же структуру добавляется ТаблицаЗначений для внутренних расчетов. Как только процедура завершается, платформа пытается вернуть измененную структуру обратно на клиент.

Проанализируем ошибочный код:


&НаКлиенте
Процедура ВыполнитьОбработку(Команда)
    ПараметрыДанных = Новый Структура("Дата", ТекущаяДата());
    ВыгрузитьНаСервере(ПараметрыДанных); // Здесь возникнет ошибка ПОСЛЕ возврата с сервера
КонецПроцедуры

&НаСервере
Процедура ВыгрузитьНаСервере(СтруктураПараметров)
    // Мы выгружаем данные в таблицу значений
    ТЗ = РезультатЗапроса.Выгрузить(); 
    // ОШИБКА: Добавляем ТЗ в структуру, которая должна вернуться на клиент
    СтруктураПараметров.Вставить("Результат", ТЗ); 
КонецПроцедуры

В данном случае проблема в том, что параметры передаются «по ссылке». Платформа видит, что СтруктураПараметров изменилась, и пытается передать её содержимое на клиент. Но клиент «не знает», что такое ТаблицаЗначений, и возникает ошибка отображения типов.

Решение: Использование ключевого слова Знач

Самый простой и эффективный способ решить проблему, если нам не нужно возвращать измененную структуру на клиент — это использование ключевого слова Знач (Val) в заголовке серверной процедуры. Это заставляет систему передавать параметры «по значению», создавая локальную копию объекта на сервере. Все изменения, внесенные в структуру внутри процедуры, будут уничтожены при выходе из неё и не полетят обратно на клиент.

Посмотрим на исправленный код:


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

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

Сценарий 2: Ошибка с типом «ОписаниеОповещения»

В современных конфигурациях (особенно на базе БСП) часто встречается ошибка, связанная с типом ОписаниеОповещения. Это часто происходит при обновлении платформы или конфигурации, когда в типовые структуры параметров (например, при сканировании штрихкодов или работе с торговым оборудованием) добавляются новые поля для асинхронной работы.

Выясним причину: объект ОписаниеОповещения создается на клиенте для того, чтобы система знала, какую процедуру вызвать после завершения какого-либо действия. Если этот объект попадает в структуру, передаваемую на сервер через ОткрытьФорму или серверный вызов, происходит сбой сериализации.

Разберем, как это исправить. Если вы обнаружили в отладке, что в вашей структуре ПараметрыСканирования или аналогичной сидит ОписаниеОповещения, просто очистите это поле перед вызовом сервера:


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

Как вернуть данные таблицы значений на клиент?

Иногда нам действительно нужно получить данные из таблицы значений, сформированной на сервере, и отобразить их на клиенте. Поскольку саму ТаблицуЗначений передать нельзя, мы должны преобразовать её в типы, которые поддерживают сериализацию: Массив и Структура.

Рассмотрим по шагам, как это реализовать:

  1. На сервере создаем Массив.
  2. Обходим ТаблицуЗначений в цикле.
  3. Для каждой строки создаем Структуру, где ключи — это имена колонок, а значения — данные строки.
  4. Добавляем структуру в массив.
  5. Возвращаем массив на клиент.

Пример реализации:


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

Альтернативный метод: Временное хранилище

Если данных очень много и преобразовывать их в массив структур слишком долго или затратно по памяти, проанализируем метод использования Временного хранилища. Этот способ позволяет сохранить серверный объект в специальной области памяти и передать на клиент только короткую строковую ссылку (адрес).


&НаСервере
Функция ПоместитьТаблицуВХранилище()
    ТЗ = ДанныеЗапроса.Выгрузить();
    // Помещаем объект в хранилище, привязывая к УИД формы
    Адрес = ПоместитьВоВременноеХранилище(ТЗ, ЭтаФорма.УникальныйИдентификатор);
    Возврат Адрес; // Возвращаем только строку
КонецФункции

На клиенте мы получим Адрес, который в дальнейшем сможем передать в другую серверную процедуру или использовать для заполнения реквизитов формы. Это исключает необходимость прямой передачи тяжелых и несовместимых объектов через XML-пакеты XDTO.

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

← На главную