Delphi 2007 генерирует неправильные сообщения SOAP - PullRequest
6 голосов
/ 19 января 2010

Я пишу приложение в Delphi 2007, которое использует веб-сервис. Я использовал импортер WSDL для генерации кода, необходимого для взаимодействия со службой, но при попытке использования службы я получаю ошибки «неожиданный субэлемент (имя элемента)».

Используя Fiddler 2, я обнаружил, что проблема заключается в том, что xmlns добавляется в массив значений, отправляемых в сообщении SOAP:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="..." xmlns:xsd="..." xmlns:xsi="...">
<SOAP-ENV:Body>
  <Request xmlns="http://service.com/theService/">
    <UserName xmlns="">user</UserName>
    <Password xmlns="">pass</Password>
    <List xmlns="">
      <Item xmlns="http://service.com/theService/">123456</Item>
      <Item xmlns="http://service.com/theService/">84547</Item>
    </List>
  </Request>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Если я повторно отправлю сообщение, созданное Delphi в Fiddler, заменив xmlns для элементов Item на пустую строку, я больше не получу сообщение об ошибке, и служба ответит правильно. то есть:

<List xmlns="">
  <Item xmlns="">123456</Item>
  <Item xmlns="">84547</Item>
</List>

Теперь я могу избавиться от атрибута xmlns для элементов списка, изменив часть инициализации моего класса обслуживания с:

InvRegistry.RegisterInvokeOptions(TypeInfo(ServicePort), ioDocument);
InvRegistry.RegisterInvokeOptions(TypeInfo(ServicePort), ioLiteral);
RemClassRegistry.RegisterSerializeOptions(RequestType, [xoLiteralParam]);

до:

InvRegistry.RegisterInvokeOptions(TypeInfo(ServicePort), ioDocument);
RemClassRegistry.RegisterSerializeOptions(RequestType, [xoHolderClass, xoLiteralParam]);

Однако это приведет к тому, что имя элемента Request изменится на имя действия SOAP по умолчанию (например, GetInformation), что снова приведет к ошибке. Я слишком долго боролся с этим, любые идеи были бы оценены.

Кроме того, я создал тестовое приложение на C #, которое использует сервис, и у него нет проблем с подключением к сервису.

1 Ответ

7 голосов
/ 23 января 2010

Я общался с другими людьми, у которых были похожие проблемы с сериализацией в Delphi, и кажется, что нет четкого способа исправить эту проблему.

Вместо этого, решение, которое я выбралс - это присоединение обработчика события к событию OnBeforeExecute объекта THTTPRIO, который отправляет сообщение SOAP, которое дает вам доступ к сериализованному сообщению мыла в виде строки.Оттуда я только что разобрал атрибут, который вызывал проблему, и теперь все работает.

Немного некрасивое решение, но оно работает.

...