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