Как исправить ошибку «Неверный формат: message.GetDataTableHttpPostOut part.Body» при подключении к веб-сервису в 1С

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

При работе с внешними веб-сервисами в платформе 1С:Предприятие часто возникает задача получить данные из сторонней системы. Однако при попытке инициализировать WSDL-схему с помощью конструктора WSОпределения программисты сталкиваются с ошибкой вида «Неверный формат. message.GetDataTableHttpPostOut part.Body Тип части сообщения не задан». Разберем причинно-следственную связь этой проблемы и рассмотрим пошаговый алгоритм её диагностики и решения.

Выясняем причину возникновения ошибки

Сформулируем, почему платформа 1С выдает подобное сообщение. Проблема заключается в особенностях генерации WSDL-документов веб-сервисами, созданными на платформе Microsoft .NET (файлы с расширением .asmx).

Сервисы .NET по умолчанию формируют описание WSDL сразу для нескольких протоколов: SOAP 1.1, SOAP 1.2, HTTP GET и HTTP POST. В блоках, описывающих протоколы HTTP GET и HTTP POST, автоматически создаются служебные сообщения (например, GetDataTableHttpGetOut и GetDataTableHttpPostOut), в которых присутствуют теги <wsdl:part name="Body" /> без явного указания типа данных (отсутствуют атрибуты type или element).

Встроенный валидатор WSDL в 1С строго анализирует весь документ полностью, включая неиспользуемые секции. Встретив элемент part без типа данных, платформа прерывает считывание схемы и генерирует исключение Неверный формат.

Шаг 1. Пошаговая диагностика сетевого доступа и WSDL

Перед тем как править схему или менять код в 1С, необходимо убедиться, что сетевой доступ к веб-сервису функционирует корректно и проблема не связана с настройками сети или авторизацией.

  1. Проверка WSDL в браузере. Откроем браузер на том компьютере, где выполняется код 1С, и перейдем по адресу веб-сервиса с параметром ?WSDL в конце ссылки. Если браузер не открывает XML-дерево схемы, значит, проблема в сети: заблокирован IP-адрес, требуется прокси-сервер или авторизация на уровне веб-сервера.
  2. Проверка контекста исполнения (Клиент / Сервер). Помним, что если код выполняется на сервере 1С:Предприятия, то сетевое обращение к веб-сервису идет от лица серверного процесса (rphost). Если в браузере на клиенте ссылка открывается, а в 1С на сервере нет — проверьте сетевые доступы и настройки прокси для сервера 1С.
  3. Тестирование в SoapUI. Для проверки корректности работы самого сервиса загрузим WSDL-ссылку в сторонний инструмент (например, SoapUI). Если SoapUI успешно отправляет запросы и принимает ответы, значит поставщик сервиса работает исправно.

Способ 1. Использование локального отредактированного WSDL-файла

Самый простой и эффективный способ обойти жесткие ограничения валидатора 1С — скачанный WSDL-файл с удаленными HTTP-binding секциями.

  1. Откроем ссылку WSDL в браузере и сохраним страницу на диск в виде файла с расширением .wsdl или .xml.
  2. Откроем сохраненный файл в любом текстовом редакторе.
  3. Найдем и удалим блоки <wsdl:message>, вызывающие ошибку, — все сообщения, содержащие в названии HttpPostOut и HttpGetOut. Также можно удалить секции <wsdl:binding> и <wsdl:port>, относящиеся к HTTP-GET и HTTP-POST, оставив только SOAP.
  4. Альтернативно можно найти строчки <wsdl:part name="Body" /> и вручную дописать тип данных, например: <wsdl:part name="Body" type="s:string" />.
  5. Сохраним файл и передадим локальный путь к нему в конструктор WSОпределения.

Рассмотрим пример кода 1С с загрузкой локального WSDL-файла:


ПутьКФайлуWSDL = "C:\WS\Airspace.wsdl";
Пользователь = "ЛогинСервиса";
Пароль = "ПарольСервиса";

Попытка
    // Загружаем исправленное локальное определение WSDL
    Определение = Новый WSОпределения(ПутьКФайлуWSDL, Пользователь, Пароль);
    
    // Создаем прокси для обращения к SOAP-сервису
    WSПрокси = Новый WSПрокси(Определение, "http://tempuri.org/", "Airspace", "AirspaceSoap");
    WSПрокси.Пользователь = Пользователь;
    WSПрокси.Пароль = Пароль;
    
    // Вызываем нужную функцию веб-сервиса
    Результат = WSПрокси.GetAirspaceData(ТокенАвторизации);
Исключение
    Сообщить("Ошибка при вызове веб-сервиса: " + ОписаниеОшибки());
КонецПопытки;

Способ 2. Прямой вызов веб-сервиса через HTTPСоединение

Если WSDL-схема часто меняется на стороне поставщика или нет возможности хранить файл на диске, откажемся от механизмов WSОпределения и WSПрокси в пользу прямых HTTP-запросов. Мы сформируем SOAP XML-конверт вручную и отправим его через объект HTTPСоединение.

Проанализируем пример выполнения прямого SOAP-запроса:


Сервер = "websvc.matfmc.ru";
АдресРесурса = "/CBD2/1.0/Airspace.asmx";

// Формируем текст SOAP-конверта
ТекстЗапросаXML = 
"<?xml version=""1.0"" encoding=""utf-8""?>
|<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
|               xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" 
|               xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
|  <soap:Body>
|    <GetAirspaceData xmlns=""http://tempuri.org/"">
|      <token>" + ТокенАвторизации + "</token>
|    </GetAirspaceData>
|  </soap:Body>
|</soap:Envelope>";

Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Заголовки.Вставить("SOAPAction", "http://tempuri.org/GetAirspaceData");

HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстЗапросаXML, КодировкаТекста.UTF8);

HTTPСоединение = Новый HTTPСоединение(Сервер);

Попытка
    ОтветHTTP = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
    Если ОтветHTTP.КодСостояния = 200 Тогда
        ТекстОтветаXML = ОтветHTTP.ПолучитьТелоКакСтроку();
        // Разбираем полученный XML через ЧтениеXML
    Иначе
        Сообщить("Ошибка HTTP: " + ОтветHTTP.КодСостояния);
    КонецЕсли;
Исключение
    Сообщить("Ошибка соединения: " + ОписаниеОшибки());
КонецПопытки;

Способ 3. Отключение HTTP GET/POST на стороне поставщика

Если у вашей команды есть доступ к серверу, где развернут веб-сервис, проблему можно решить системно. В файле конфигурации web.config .NET-приложения достаточно отключить протоколы HTTP-GET и HTTP-POST для генерации WSDL, оставив только SOAP.

Для этого в секции <system.web> файла web.config необходимо ограничить протоколы:


<webServices>
  <protocols>
    <remove name="HttpGet" />
    <remove name="HttpPost" />
  </protocols>
</webServices>

После внесения этого изменения веб-сервис начнет отдавать чистый WSDL, который без ошибок обрабатывается встроенным объектом WSОпределения в 1С.

← На главную