Как изменить имя возвращаемого тега return в SOAP Web-сервисе 1С?

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

При интеграции 1С с внешними системами через SOAP Web-сервисы разработчики часто сталкиваются с жестким поведением платформы 1С:Предприятие. По умолчанию, когда операция Web-сервиса возвращает данные, платформа оборачивает результат в XML-тег <return>. Однако внешние системы, ранее интегрированные со сторонним ПО (например, на Java, .NET или PHP), могут ожидать специфическое имя тега (например, <GetAllWkCargoesResult> или <Items>). Платформа 1С напрямую не позволяет изменить имя возвращаемого тега в свойствах операции Web-сервиса.

В этой статье мы подробно рассмотрим причины такого поведения платформы и разберем четыре практических способа решения этой проблемы: от штатного изменения параметров метаданных до модификации ответов на веб-сервере.

Выясняем причину: почему появляется тег return?

Платформа 1С самостоятельно управляет сериализацией SOAP-сообщений на основе стандартов WSDL. Когда для операции Web-сервиса задается «Тип возвращаемого значения», это указывает платформе, что функция должна вернуть одно конкретное значение. Согласно внутренним алгоритмам платформы, это возвращаемое значение всегда упаковывается в элемент <return> внутри тела ответа (SOAP Body). Изменить это имя через свойства XDTO-пакета или настройки операции в конфигураторе невозможно, так как это поведение жестко зашито в платформу 1С.

Разберем подробнее, какие альтернативные подходы мы можем использовать для решения этой задачи.

Способ 1. Использование выходных параметров (Штатное решение в 1С)

Это самый чистый и элегантный способ избавиться от тега <return> средствами самой платформы 1С, без привлечения стороннего софта или написания сложных оберток.

Суть метода заключается в том, что мы отказываемся от использования возвращаемого значения функции Web-сервиса (делаем операцию процедурой, возвращающей void), а все данные передаем через Выходной параметр операции. Платформа 1С для выходных параметров использует их реальные имена в качестве XML-тегов в SOAP-ответе.

Разберем этот способ по шагам:

  1. Откройте конфигуратор 1С и перейдите к вашему Web-сервису.
  2. Найдите нужную операцию и откройте ее палитру свойств.
  3. Очистите поле «Тип возвращаемого значения» (оставьте его пустым). Это укажет платформе, что операция не возвращает значение напрямую.
  4. Перейдите на вкладку «Параметры» этой операции и добавьте новый параметр.
  5. Задайте параметру то имя, которое ожидает внешняя система (например, MyCustomResponseName).
  6. В свойстве «Направление передачи» этого параметра выберите значение «Выходной» (Output).
  7. Укажите нужный «Тип значения» (это может быть простой тип или тип из вашего XDTO-пакета).
  8. В модуле Web-сервиса измените код функции. Вместо оператора Возврат присвойте результат непосредственно переменной созданного параметра.

Посмотрим на пример кода в модуле Web-сервиса:


Процедура ПолучитьДанные(КодМобильногоКомпьютера, MyCustomResponseName)
    УстановитьПривилегированныйРежим(Истина);
    
    УзелОбмена = ПланыОбмена.МобильноеПриложение.НайтиПоКоду(КодМобильногоКомпьютера);
    Если УзелОбмена.Пустая() Тогда
        ВызватьИсключение(НСтр("ru='Неизвестное устройство - '") + КодМобильногоКомпьютера);
    КонецЕсли;
    
    // Формируем пакет данных (например, XDTO-объект)
    ДанныеПакета = ОбменМобильноеПриложениеОбщее.СформироватьЕдиныйПакетВыгрузки(УзелОбмена);
    
    // Вместо возврата значения, присваиваем его выходному параметру
    MyCustomResponseName = ДанныеПакета;
КонецПроцедуры

В результате вызова этой операции платформа сгенерирует следующий SOAP-ответ:


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ПолучитьДанныеResponse xmlns="http://www.yourcompany.ru/mobi">
         <MyCustomResponseName>
            <!-- Здесь будут находиться сериализованные данные XDTO -->
         </MyCustomResponseName>
      </ПолучитьДанныеResponse>
   </soap:Body>
</soap:Envelope>

Этот способ полностью решает проблему, сохраняя при этом все преимущества автоматической сериализации XDTO и контроля типов платформой 1С.

Способ 2. Модификация SOAP-ответа на уровне веб-сервера

Если ваша конфигурация находится на поддержке, или вы не хотите менять структуру метаданных Web-сервиса, можно настроить модификацию XML-ответа «на лету» прямо на веб-сервере (Apache или IIS). Это надежное промышленное решение, работающее как прозрачный middleware (промежуточное ПО).

Настройка для веб-сервера Apache

Для замены тегов в Apache используется стандартный модуль mod_substitute. Он позволяет проводить контекстную замену текста в теле HTTP-ответов по регулярным выражениям.

Выполним настройку по шагам:

  1. Убедитесь, что в файле конфигурации Apache httpd.conf подключен модуль LoadModule substitute_module modules/mod_substitute.so.
  2. В блоке конфигурации вашей публикации (внутри тега <Directory> или <Location>) добавьте следующие директивы:

<Location "/BaseName/ws">
    AddOutputFilterByType SUBSTITUTE text/xml application/soap+xml
    Substitute "s|<return>|<MyCustomResponseName>|i"
    Substitute "s|</return>|</MyCustomResponseName>|i"
</Location>

При такой настройке веб-сервер будет автоматически перехватывать ответы от 1С и заменять теги <return> на нужные вам значения перед отправкой клиенту.

Настройка для веб-сервера IIS

На веб-сервере IIS аналогичная задача решается с помощью модуля URL Rewrite (модуль переписывания URL).

  1. Установите расширение URL Rewrite через Web Platform Installer.
  2. Откройте Диспетчер служб IIS, выберите ваш виртуальный каталог публикации 1С.
  3. Перейдите в раздел URL Rewrite и в панели действий нажмите Add Rule(s)....
  4. Выберите Outbound Limits / Outbound Rules (Правила исходящего трафика).
  5. Настройте правило на сопоставление ответов с типом контента text/xml и укажите замену подстрок <return> на <MyCustomResponseName>.

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

Когда мы меняем структуру XML-ответов сторонними средствами (например, через веб-сервер), динамически генерируемый файл описания сервиса (WSDL), доступный по адресу ...?wsdl, все еще будет содержать упоминание элемента name="return". Это может приводить к ошибкам валидации на стороне клиента.

Чтобы этого избежать, мы можем использовать статический WSDL-файл:

  1. Скачайте автоматически сгенерированный WSDL-файл вашего сервиса, перейдя по ссылке http://server/base/ws/service?wsdl.
  2. Откройте файл в текстовом редакторе и найдите описание типов возвращаемых значений.
  3. Замените вхождение name="return" на имя вашего кастомного тега (например, name="MyCustomResponseName").
  4. Сохраните файл под именем service.wsdl и положите его в каталог публикации на веб-сервере.
  5. Предоставьте клиенту ссылку на этот статический файл WSDL. Веб-сервер будет отдавать скорректированную схему, а сами запросы будут уходить в 1С.

Способ 4. Переход на HTTP-сервисы с ручным формированием SOAP

Выясним причину, почему разработчики часто выбирают HTTP-сервисы. Если вам требуется абсолютный контроль над структурой XML, включая пространства имен, заголовки SOAP-конверта и любые кастомные теги, идеальным решением будет отказ от использования встроенных SOAP Web-сервисов 1С в пользу HTTP-сервисов.

HTTP-сервисы в 1С не накладывают никаких ограничений на формат передаваемых данных. Вы можете вручную сформировать любой XML-документ (в том числе полностью повторяющий структуру SOAP) с помощью встроенного объекта ЗаписьXML и вернуть его как тело HTTP-ответа.

Проанализируем пример кода реализации SOAP-ответа через HTTP-сервис:


Функция ПолучитьДанныеHTTP(Запрос)
    
    // Инициализируем запись XML в строку
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку("UTF-8");
    
    // Формируем структуру SOAP вручную
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    ЗаписьXML.ЗаписатьНачалоЭлемента("soap:Envelope");
    ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("soap", "http://schemas.xmlsoap.org/soap/envelope/");
    ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("mobi", "http://www.yourcompany.ru/mobi");
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("soap:Body");
    ЗаписьXML.ЗаписатьНачалоЭлемента("mobi:ПолучитьДанныеResponse");
    
    // Формируем кастомный тег вместо return
    ЗаписьXML.ЗаписатьНачалоЭлемента("mobi:MyCustomResponseName");
    
    // Сюда мы можем записать данные XDTO или обычный XML-текст
    ЗаписьXML.ЗаписатьТекст("Результат работы сервиса");
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // MyCustomResponseName
    ЗаписьXML.ЗаписатьКонецЭлемента(); // ПолучитьДанныеResponse
    ЗаписьXML.ЗаписатьКонецЭлемента(); // soap:Body
    ЗаписьXML.ЗаписатьКонецЭлемента(); // soap:Envelope
    
    РезультатXML = ЗаписьXML.Закрыть();
    
    // Формируем HTTP-ответ с корректным заголовком Content-Type
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
    Ответ.УстановитьТелоИзСтроки(РезультатXML, КодировкаТекста.UTF8);
    
    Возврат Ответ;
    
КонецФункции

Этот способ сложнее в реализации, так как требует ручной обработки входящих SOAP-запросов и парсинга XML, но он дает 100% гарантию совместимости с любыми внешними системами, независимо от их требований к именованию XML-элементов.

Резюме

Мы рассмотрели несколько способов решения проблемы с навязанным тегом <return>. Наиболее рекомендуемым и простым в реализации является Способ 1 (выходные параметры), так как он выполняется полностью средствами конфигуратора 1С и не требует стороннего вмешательства. Если же менять конфигурацию нельзя, используйте Способ 2 (модификация на веб-сервере). В случаях экстремальных требований к формату XML отличным выбором станет переход на HTTP-сервисы (Способ 4).

← На главную