При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с диагностическим сообщением и выполняют анализ конфигурации на наличие ошибок (поможет инструментарий отладки и анализа метаданных): «Ошибка отображения типов: Отсутствует отображение для типа... по причине: Ошибка преобразования данных XDTO». Эта проблема возникает в момент взаимодействия между тонким клиентом и сервером (больше информации в нашей базе знаний). Давайте подробно используя статический анализатор кода разберем, почему это происходит, как работает механизм сериализации и какие существуют проверенные способы решения этой задачи.
Для того чтобы понять суть проблемы, проанализируем, как 1С передает информацию «по проводам» (иногда требуется адаптивная выгрузка данных XML). Когда мы вызываем серверную процедуру из клиентского контекста, платформа должна превратить программные объекты (структуры, массивы, запросы) в универсальный формат передачи данных — XML. Этот процесс называется сериализацией. На обратном пути, когда выполнение серверного кода завершается, происходит десериализация — данные превращаются обратно в объекты 1С.
Ошибка «Отсутствует отображение для типа» означает, что в составе передаваемых данных оказался объект, тип которого не поддерживается в целевом контексте или не может быть описан схемой XDTO. Чаще всего это случается с объектами, которые существуют только на сервере, но «случайно» пытаются вернуться на клиент.
Основные типы-нарушители:
Рассмотрим классическую ситуацию из практики. Программист передает с клиента на сервер структуру с параметрами. Внутри серверной процедуры в эту же структуру добавляется ТаблицаЗначений для внутренних расчетов. Как только процедура завершается, платформа пытается вернуть измененную структуру обратно на клиент.
Проанализируем ошибочный код:
&НаКлиенте
Процедура ВыполнитьОбработку(Команда)
ПараметрыДанных = Новый Структура("Дата", ТекущаяДата());
ВыгрузитьНаСервере(ПараметрыДанных); // Здесь возникнет ошибка ПОСЛЕ возврата с сервера
КонецПроцедуры
&НаСервере
Процедура ВыгрузитьНаСервере(СтруктураПараметров)
// Мы выгружаем данные в таблицу значений
ТЗ = РезультатЗапроса.Выгрузить();
// ОШИБКА: Добавляем ТЗ в структуру, которая должна вернуться на клиент
СтруктураПараметров.Вставить("Результат", ТЗ);
КонецПроцедуры
В данном случае проблема в том, что параметры передаются «по ссылке». Платформа видит, что СтруктураПараметров изменилась, и пытается передать её содержимое на клиент. Но клиент «не знает», что такое ТаблицаЗначений, и возникает ошибка отображения типов.
Самый простой и эффективный способ решить проблему, если нам не нужно возвращать измененную структуру на клиент — это использование ключевого слова Знач (Val) в заголовке серверной процедуры. Это заставляет систему передавать параметры «по значению», создавая локальную копию объекта на сервере. Все изменения, внесенные в структуру внутри процедуры, будут уничтожены при выходе из неё и не полетят обратно на клиент.
Посмотрим на исправленный код:
&НаСервере
Процедура ВыгрузитьНаСервере(Знач СтруктураПараметров) // Добавили Знач
ТЗ = Таблица.Выгрузить();
СтруктураПараметров.Вставить("Таблица", ТЗ);
// Теперь ТЗ живет только внутри этой процедуры и не вызывает ошибку
МодульОбъекта = РеквизитФормыВЗначение("Объект");
МодульОбъекта.ОбработатьДанные(СтруктураПараметров);
КонецПроцедуры
Важный нюанс: Если вы используете функцию, возвращающую значение, убедитесь, что возвращаемый объект (например, новая структура) также не содержит внутри себя запрещенных типов.
В современных конфигурациях (особенно на базе БСП) часто встречается ошибка, связанная с типом ОписаниеОповещения. Это часто происходит при обновлении платформы или конфигурации, когда в типовые структуры параметров (например, при сканировании штрихкодов или работе с торговым оборудованием) добавляются новые поля для асинхронной работы.
Выясним причину: объект ОписаниеОповещения создается на клиенте для того, чтобы система знала, какую процедуру вызвать после завершения какого-либо действия. Если этот объект попадает в структуру, передаваемую на сервер через ОткрытьФорму или серверный вызов, происходит сбой сериализации.
Разберем, как это исправить. Если вы обнаружили в отладке, что в вашей структуре ПараметрыСканирования или аналогичной сидит ОписаниеОповещения, просто очистите это поле перед вызовом сервера:
&НаКлиенте
Процедура ОбработатьСобытие(Параметры)
// Если нам нужно передать параметры на сервер,
// но там есть несериализуемое оповещение:
ПараметрыДляСервера = Новый Структура;
ЗаполнитьЗначенияСвойств(ПараметрыДляСервера, Параметры);
// Явно удаляем или зануляем проблемный тип
Если ПараметрыДляСервера.Свойство("Оповещение") Тогда
ПараметрыДляСервера.Оповещение = Неопределено;
КонецЕсли;
ВызватьСервернуюФункцию(ПараметрыДляСервера);
КонецПроцедуры
Иногда нам действительно нужно получить данные из таблицы значений, сформированной на сервере, и отобразить их на клиенте. Поскольку саму ТаблицуЗначений передать нельзя, мы должны преобразовать её в типы, которые поддерживают сериализацию: Массив и Структура.
Рассмотрим по шагам, как это реализовать:
Массив.ТаблицуЗначений в цикле.Структуру, где ключи — это имена колонок, а значения — данные строки.Пример реализации:
&НаСервере
Функция ПолучитьДанныеДляКлиента()
ТЗ = СформироватьЗапросИПолучитьТаблицу();
СписокРезультатов = Новый Массив;
Для Каждого СтрокаТЗ Из ТЗ Цикл
НоваяСтрока = Новый Структура("Артикул, Цена, Остаток");
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
СписокРезультатов.Добавить(НоваяСтрока);
КонецЦикла;
Возврат СписокРезультатов; // Массив структур успешно передастся на клиент
КонецФункции
Если данных очень много и преобразовывать их в массив структур слишком долго или затратно по памяти, проанализируем метод использования Временного хранилища. Этот способ позволяет сохранить серверный объект в специальной области памяти и передать на клиент только короткую строковую ссылку (адрес).
&НаСервере
Функция ПоместитьТаблицуВХранилище()
ТЗ = ДанныеЗапроса.Выгрузить();
// Помещаем объект в хранилище, привязывая к УИД формы
Адрес = ПоместитьВоВременноеХранилище(ТЗ, ЭтаФорма.УникальныйИдентификатор);
Возврат Адрес; // Возвращаем только строку
КонецФункции
На клиенте мы получим Адрес, который в дальнейшем сможем передать в другую серверную процедуру или использовать для заполнения реквизитов формы. Это исключает необходимость прямой передачи тяжелых и несовместимых объектов через XML-пакеты XDTO.
Подведем итог: Ошибка отображения типов — это всегда сигнал о том, что нарушена граница применимости объектов. Всегда проверяйте состав ваших структур в отладке (поможет инструмент отладки кода и просмотра переменных) перед вызовом сервера и используйте Знач, если возвращать измененный объект не требуется.