При интеграции 1С со сторонними системами через протокол SOAP часто возникает задача передачи параметров сложной структуры. В отличие от простых типов (число, строка, дата), составные типы данных и массивы объектов нельзя передать напрямую через стандартные коллекции 1С (такие как Структура или Массив). Для их корректной сериализации и передачи платформой 1С используется механизм XDTO (XML Data Transfer Objects).
Разберем по шагам, как правильно подготовить и передать составной объект и массив данных в SOAP веб-сервис как при использовании статической ссылки (объекта конфигурации WS-ссылки), так и при динамическом подключении через WSОпределения.
Проанализируем ситуацию, когда WSDL-схема уже импортирована в дерево метаданных конфигурации в ветку WS-ссылки. В этом случае фабрика XDTO доступна напрямую из объекта WSПрокси.
Выясним последовательность действий для передачи составного типа:
СоздатьWSПрокси.ФабрикаXDTO нашего прокси-объекта.ФабрикаXDTO.Тип(), передав URI пространства имен схемы и имя сложного типа.ФабрикаXDTO.Создать().ОбъектXDTO значениями и передаем его в метод сервиса.Посмотрим на пример кода:
// Инициализируем объект-посредник
НашСервис = WSСсылки.Портал.СоздатьWSПрокси("URI_ПространстваИменСервиса", "ИмяСервиса", "ИмяТочкиПодключения");
// Получаем фабрику XDTO сервиса
Фабрика = НашСервис.ФабрикаXDTO;
// Получаем тип составного параметра по пространству имен XSD-схемы и имени типа
ТипПараметра = Фабрика.Тип("http://external-system.org/types", "CustomerData");
// Создаем экземпляр сложного типа
СоставнойПараметр = Фабрика.Создать(ТипПараметра);
// Заполняем поля объекта
СоставнойПараметр.Поле1 = ЗначениеПоля1;
СоставнойПараметр.Поле2 = ЗначениеПоля2;
СоставнойПараметр.Поле3 = ЗначениеПоля3;
// Вызываем метод веб-сервиса
Результат = НашСервис.RegisterCustomer(СоставнойПараметр);
Рассмотрим подробнее вариант, когда WSDL-файл загружается динамически по сетевому адресу (URL) без сохранения в метаданных конфигурации 1С. В этом случае фабрику типов предоставляет объект WSОпределения.
Посмотрим на пример реализации динамического вызова:
АдресWSDL = "http://api.service.com/service.wsdl";
Определение = Новый WSОпределения(АдресWSDL, ЛогинWS, ПарольWS);
ПространствоИменСервиса = "http://api.service.com/ws";
ИмяСервиса = "MainService";
ИмяТочкиПодключения = "MainServiceSoapPort";
Прокси = Новый WSПрокси(Определение, ПространствоИменСервиса, ИмяСервиса, ИмяТочкиПодключения);
Фабрика = Определение.ФабрикаXDTO;
// Создаем объект требуемого типа
ТипОбъекта = Фабрика.Тип(ПространствоИменСервиса, "TestClass41");
ОбъектСервиса = Фабрика.Создать(ТипОбъекта);
ОбъектСервиса.a = Параметр41;
ОбъектСервиса.b = Параметр42;
ОбъектСервиса.res = 0;
// Выполняем вызов метода веб-сервиса
ОбъектРезультат = Прокси.test4(ОбъектСервиса);
Результат = ОбъектРезультат.res;
Часто в методах веб-сервисов требуется передать не просто один объект, а список однотипных записей (в XSD-схеме такое свойство описывается атрибутом maxOccurs="unbounded"). В объектной модели 1С такие поля представляются типом СписокXDTO.
Важное правило: прямое присвоение массива 1С (например, ОбъектСервиса.arr = Массив1С) вызовет ошибку несоответствия типов. Наполнение списка выполняется строго с помощью метода Добавить() у свойства-коллекции родительского объекта XDTO.
Разберем по шагам заполнение составного массива:
Родитель.Список.Добавить(Элемент).Посмотрим на пример кода заполнения массива и обработки полученного ответа:
Определение = Новый WSОпределения(АдресWSDL);
Прокси = Новый WSПрокси(Определение, ПространствоИменСервиса, ИмяСервиса, ИмяТочкиПодключения);
Фабрика = Определение.ФабрикаXDTO;
// Создаем корневой составной объект
ОбъектСервиса = Фабрика.Создать(Фабрика.Тип(ПространствоИменСервиса, "TestClass51"));
// Получаем тип вложенных элементов массива
ТипЭлементаСписка = Фабрика.Тип(ПространствоИменСервиса, "TestClass52");
// Наполняем свойство arr элементами
Для Каждого Стр Из ТаблицаПараметров Цикл
Элемент = Фабрика.Создать(ТипЭлементаСписка);
ЗаполнитьЗначенияСвойств(Элемент, Стр);
ОбъектСервиса.arr.Добавить(Элемент);
КонецЦикла;
// Вызов веб-сервиса
ОбъектРезультат = Прокси.test5(ОбъектСервиса);
// Чтение массива из ответа сервиса
Результат = Новый Массив;
Для Каждого ЭлементРезультата Из ОбъектРезультат.res Цикл
Результат.Добавить(ЭлементРезультата);
КонецЦикла;
Проанализируем ключевые нюансы, которые необходимо учитывать при передаче параметров через XDTO:
Фабрика.Тип(URI, ИмяТипа) необходимо указывать точный URI схемы, где объявлен конкретный тип.xs:sequence, порядок инициализации свойств объекта XDTO должен строго соответствовать порядку, объявленному в схеме. Нарушение последовательности может приводить к ошибкам валидации XML на стороне сервера.nillable="true", передача значения Неопределено вызовет исключение. Если свойство опционально (minOccurs="0"), для корректной сериализации его лучше не трогать вовсе, чтобы не генерировать пустые некорректные XML-узлы.