Разработка мобильных приложений на платформе 1С:Предприятие часто сопровождается трудностями при обмене данными через веб-сервисы. Типичная ситуация: веб-сервис успешно проходит тесты в SoapUI, корректно отдает данные десктопному клиенту, но при вызове из мобильного приложения возвращает ошибку: Ошибка проверки данных XDTO: Структура объекта не соответствует типу... Отсутствует обязательное свойство. Проанализируем, почему это происходит и как решить данную проблему несколькими способами.
Первое, что мы должны понять: мобильная платформа 1С значительно строже относится к проверке XDTO-пакетов, чем обычный клиент или сторонние инструменты типа SoapUI. В то время как SoapUI может проигнорировать отсутствие некоторых полей, мобильный клиент выполняет полную валидацию полученного XML-ответа на соответствие схеме WSDL.
Если в схеме XSD свойство (например, ApplicationReestr) помечено как обязательное (параметр minOccurs="1"), а в формируемом на сервере объекте это свойство не заполнено или равно Неопределено, мобильное приложение прервет операцию с ошибкой. Рассмотрим, как выглядит типичный вызов сервиса из мобильного кода:
АдресСервиса = "http://server/base/ws/service?wsdl";
Пользователь = "USER";
Пароль = "PASS";
Определения = Новый WSОпределения(АдресСервиса, Пользователь, Пароль,, 60);
URI = Определения.Сервисы[0].URIПространстваИмен;
Прокси = Новый WSПрокси(Определения, URI, "bit_ApprovalService", "bit_ApprovalServiceSoap",, 600);
Прокси.Пользователь = Пользователь;
Прокси.Пароль = Пароль;
// Вызов метода, вызывающий ошибку
Результат = Прокси.GetObjectsForApproval(Пользователь, "бит_ЗаявкаНаРасходованиеСредств", Дата(2018,02,09), Дата(2018,02,09,23,59,59));
Проанализируем процесс формирования ответа на стороне веб-сервиса. Часто разработчики забывают инициализировать сложные свойства, если в них нет данных. Если ApplicationReestr является вложенным объектом, его недостаточно просто «пропустить» — его нужно создать через ФабрикаXDTO.
Рассмотрим пример правильного формирования ответа на сервере, где мы последовательно создаем все уровни вложенности:
Пакет = ФабрикаXDTO.Пакеты.Получить("http://www.bit-cly.ru/Approval");
ТипСписок = Пакет.Получить("ApprovalList");
ЗначениеСписок = ФабрикаXDTO.Создать(ТипСписок);
ТипЭлемент = Пакет.Получить("ApprovalListItem");
ТипРеестр = Пакет.Получить("ApplicationReestr");
Для каждого СтрокаТаблицы Из ТаблицаДокументов Цикл
НовыйЭлемент = ФабрикаXDTO.Создать(ТипЭлемент);
// ВАЖНО: Если свойство ApplicationReestr обязательно по схеме,
// создаем его экземпляр, даже если оно будет пустым.
ОбъектРеестра = ФабрикаXDTO.Создать(ТипРеестр);
НовыйЭлемент.ApplicationReestr = ОбъектРеестра;
// Заполнение остальных свойств
НовыйЭлемент.ObjectID = СтрокаТаблицы.Ссылка.УникальныйИдентификатор();
ЗначениеСписок.Rows.Добавить(НовыйЭлемент);
КонецЦикла;
Возврат ЗначениеСписок;
Выясним причину: если в определении типа ApprovalListItem поле ApplicationReestr имеет минимальное количество = 1, то отсутствие присваивания НовыйЭлемент.ApplicationReestr = ... приведет к краху мобильного клиента, даже если сам XML визуально кажется верным.
Мобильная платформа крайне чувствительна к соответствию пространств имен. Если тип данных определен в одном Namespace, а используется в другом, и при генерации XML на сервере происходит автоматическое приведение типов, мобильный клиент может «потерять» описание свойства. Проверьте, чтобы в коде сервера при получении типов использовался корректный URI, совпадающий с тем, что ожидает клиент.
Посмотрим на пример из практики: использование метода Пакет.Получить() без указания точного пространства имен может привести к созданию объекта другого типа с похожим именем, что вызовет ошибку валидации при десериализации на мобильном устройстве.
Рассмотрим наиболее надежный способ взаимодействия мобильного приложения с внешними базами — передачу данных в виде строки (XML или JSON). Этот метод позволяет полностью избежать жесткой валидации XDTO на уровне платформенного вызова WSProxy.
Алгоритм действий:
Строка.XDTO в строку XML.Пример кода на сервере для превращения объекта в строку:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ЗначениеСписок);
Возврат ЗаписьXML.Закрыть();
Пример кода в мобильном приложении для обработки полученной строки:
ОтветСтрокой = Прокси.GetObjectsForApproval(Параметры);
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ОтветСтрокой);
// Читаем данные, игнорируя строгую проверку схемы при необходимости
ОбъектРезультат = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Этот подход значительно стабильнее, так как вы сами контролируете процесс разбора данных и можете обработать отсутствие необязательных полей без падения приложения.
Проанализируем ситуацию, когда вы уже внесли изменения в XDTO-пакеты на сервере (например, сделали свойство необязательным), но ошибка сохраняется. Мобильное приложение активно кэширует структуру WSОпределения. Для принудительного обновления схемы рекомендуется:
WSОпределения создается заново, а не берется из кэшированных переменных.Обратим внимание на совет из обсуждения: при передаче параметров в методы веб-сервиса (как во втором параметре метода GetObjectsForApproval), старайтесь использовать строковые представления типов или УникальныйИдентификатор вместо попыток передать ДокументСсылка напрямую. Мобильная платформа может некорректно интерпретировать ссылки основной базы, что также косвенно влияет на стабильность XDTO-сессий.
Подводя итог: если вы столкнулись с ошибкой «Отсутствует обязательное свойство», в первую очередь проверьте инициализацию всех вложенных объектов на сервере через ФабрикаXDTO.Создать(). Если структура слишком сложная и изменчивая — переходите на передачу данных через Base64 или обычную строку XML/JSON, это сэкономит время на отладку валидации в будущем.