Как исправить ошибки при возврате массива объектов XDTO через Web-сервис 1С

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

Передача сложных структур данных, таких как массивы объектов, через Web-сервисы 1С часто вызывает затруднения у разработчиков. Основные сложности связаны с настройкой XDTO-пакетов, типизацией возвращаемых значений и синхронизацией описания сервиса (WSDL) с вызывающим приложением. В этой статье мы подробно разберем, как правильно организовать возврат массива заказов, проанализируем типичные ошибки и выясним причины их возникновения.

Настройка схемы XDTO для работы с массивами

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

Чтобы свойство объекта XDTO воспринималось платформой как список (массив), необходимо в Конфигураторе для этого свойства установить следующие параметры:

  1. Минимальное количество: установим значение 0. Это позволит сервису возвращать пустой список, если заказы не найдены.
  2. Максимальное количество: установим значение -1 (в XML-схемах это соответствует unbounded). Именно этот параметр превращает обычное свойство в коллекцию, у которой появляется метод Добавить().

Например, если у нас есть тип ArrayClientOrder, содержащий свойство ClientOrder (тип ClientOrder), то без указания Максимальное количество = -1 это будет просто одиночный вложенный объект, а не массив.

Правильное заполнение коллекции XDTO в коде 1С

Проанализируем программную реализацию формирования массива. Важно помнить, что экземпляр элемента массива нужно создавать внутри цикла. Если создать объект типа ClientOrder один раз до начала цикла и просто менять его свойства, то в итоговый массив добавятся ссылки на один и тот же объект, и в результате все элементы массива будут содержать данные последнего обработанного заказа.

Рассмотрим правильный алгоритм работы с Фабрикой XDTO:


// Определяем URI и получаем пакет
URIПространстваИмен = "http://localhost/IB/ws/ClientOrders";
ПакетCML = ФабрикаXDTO.Пакеты.Получить(URIПространстваИмен);

// Получаем типы из пакета
МассивЗаказовТип = ПакетCML.Получить("ArrayClientOrder");
ЗаказТип = ПакетCML.Получить("ClientOrder");

// Создаем корневой объект (контейнер для массива)
МассивЗаказовXDTO = ФабрикаXDTO.Создать(МассивЗаказовТип);

Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
    // Создаем НОВЫЙ экземпляр для каждого шага цикла
    НовыйЗаказXDTO = ФабрикаXDTO.Создать(ЗаказТип);
    
    // Заполняем свойства (приводим к строкам для соответствия простым типам XML)
    НовыйЗаказXDTO.OrderNumber = Строка(Выборка.НомерЗаказа);
    НовыйЗаказXDTO.OrderDate   = Выборка.ДатаЗаказа; // Если в XDTO тип dateTime, Строка() не нужна
    НовыйЗаказXDTO.OrderState  = Строка(Выборка.СостояниеЗаказа);
    
    // Добавляем заполненный объект в коллекцию
    МассивЗаказовXDTO.ClientOrder.Добавить(НовыйЗаказXDTO);
КонецЦикла;

Возврат МассивЗаказовXDTO;

Проблема несоответствия типов данных

Часто возникает ошибка при установке значения атрибута контекста, например, OrderState. Разберем причину: в 1С значение Выборка.СостояниеЗаказа является ссылкой на справочник (СправочникСсылка), а в схеме XDTO для этого поля указан тип string (http://www.w3.org/2001/XMLSchema). Платформа 1С не всегда может автоматически преобразовать ссылку в строку при записи в XDTO. Поэтому мы рекомендуем явно использовать функцию Строка() для всех полей, которые в схеме описаны как строковые.

Особое внимание стоит уделить типам boolean и decimal. Если в XDTO указано, что поле IndicatorDelays имеет тип boolean, то передача туда строки "Истина" может привести к ошибке. В этом случае нужно передавать чистое значение Булево из 1С.

Ошибка XmlException на стороне клиента

Если ваше консольное приложение (на C# или другом языке) выдает ошибку вида XmlException: Непредусмотренный тип узла Element... Метод ReadElementString может быть вызван только для элементов с простым содержимым, это верный признак того, что клиент ожидает получить простую строку, а сервер прислал сложную структуру XML.

Это происходит по двум причинам:

  1. Не обновлена веб-ссылка: Вы изменили тип возвращаемого значения в 1С с string на XDTO Data Object, но клиентское приложение все еще использует старый WSDL-файл. Необходимо выполнить Update Service Reference в вашей среде разработки.
  2. Настройка WS-операции: Проверьте в Конфигураторе 1С свойства вашей операции Web-сервиса. В поле Тип возвращаемого значения должен быть выбран соответствующий тип из XDTO-пакета (например, {http://localhost/IB/ws/ClientOrders}ArrayClientOrder). Если там по ошибке указано string, 1С попытается "впихнуть" XML-структуру в текстовый узел, что и вызовет сбой у клиента.

Рекомендации по отладке

Для выяснения причин некорректного поведения веб-сервиса выполним следующие действия:

Следуя этим правилам, мы обеспечим стабильную работу интеграции и исключим большинство типичных ошибок при передаче массивов данных через Web-сервисы 1С.

← На главную