Передача сложных структур данных, таких как массивы объектов, через Web-сервисы 1С часто вызывает затруднения у разработчиков. Основные сложности связаны с настройкой XDTO-пакетов, типизацией возвращаемых значений и синхронизацией описания сервиса (WSDL) с вызывающим приложением. В этой статье мы подробно разберем, как правильно организовать возврат массива заказов, проанализируем типичные ошибки и выясним причины их возникновения.
Первая и самая распространенная проблема — ошибка Значение не является значением объектного типа (Добавить). Рассмотрим ситуацию: вы создали объект XDTO, который должен содержать список элементов, но при попытке вызвать метод Добавить() система выдает исключение. Это происходит из-за того, что в определении типа XDTO свойство не помечено как коллекция.
Чтобы свойство объекта XDTO воспринималось платформой как список (массив), необходимо в Конфигураторе для этого свойства установить следующие параметры:
0. Это позволит сервису возвращать пустой список, если заказы не найдены.-1 (в XML-схемах это соответствует unbounded). Именно этот параметр превращает обычное свойство в коллекцию, у которой появляется метод Добавить().Например, если у нас есть тип ArrayClientOrder, содержащий свойство ClientOrder (тип ClientOrder), то без указания Максимальное количество = -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С.
Если ваше консольное приложение (на C# или другом языке) выдает ошибку вида XmlException: Непредусмотренный тип узла Element... Метод ReadElementString может быть вызван только для элементов с простым содержимым, это верный признак того, что клиент ожидает получить простую строку, а сервер прислал сложную структуру XML.
Это происходит по двум причинам:
string на XDTO Data Object, но клиентское приложение все еще использует старый WSDL-файл. Необходимо выполнить Update Service Reference в вашей среде разработки.{http://localhost/IB/ws/ClientOrders}ArrayClientOrder). Если там по ошибке указано string, 1С попытается "впихнуть" XML-структуру в текстовый узел, что и вызовет сбой у клиента.Для выяснения причин некорректного поведения веб-сервиса выполним следующие действия:
URIПространстваИмен в коде совпадает с тем, что указано в самом XDTO-пакете. Любая опечатка приведет к тому, что Фабрика XDTO не сможет найти нужный тип."0" вместо объекта, если результат запроса пуст. Это плохая практика. Если операция должна возвращать объект XDTO, она всегда должна возвращать объект XDTO (пустой контейнер массива), иначе клиентское приложение упадет при попытке десериализации строки в объект.Следуя этим правилам, мы обеспечим стабильную работу интеграции и исключим большинство типичных ошибок при передаче массивов данных через Web-сервисы 1С.