Delphi SOAP Envelope和WCF

我正在开发一个提供soap接口的系统。 其中一个将使用该接口的系统在Delphi 7中编码.Web服务是使用WCF,基本的http绑定,SOAP 1.1开发的。

如果我使用SOAP UI(JAVA),该服务正常工作。 但delphi似乎在这里做了特别的事情;)

这是SOAP UI中消息的样子:

       ?     

我不是delphi开发人员,但我开发了一个简单的测试客户端,看看出了什么问题。 这就是Delphi作为SOAP信封发送的内容。

       253    

WCF抛出一个德语错误…;)

Es wurde das Endelement“Body”aus命名空间“ http://schemas.xmlsoap.org/soap/envelope/”erwartet 。 Gefunden wurde“Element”NS2:GetCustomerRequest“aus Namespace” http://services.xxx.de/xxx “”。 Zeile 1,职位599。

意味着什么

身体是预期的。 但是找到了元素“NS2:GetCustomerReques”。

现在我的问题是:我可以以某种方式改变Delphi创建信封的方式吗? 或者是使WCF使用这种消息格式的方法? 任何帮助是极大的赞赏!

与这里的一些人似乎暗示的相反,Delphi不发送无效的 SOAP,它只是发送RPC / Encoded SOAP。 从所有xsi:type属性中识别它非常容易。 RPC / Encoded不符合WS-I,但它仍然有效的SOAP。

默认情况下,WCF使用Document / Literal / Wrapped SOAP格式,Delphi 7在服务器端根本无法处理,您必须在客户端进行一些调整。

最简单的解决方案是简单地告诉Delphi使用Document / Literal样式。 您可以通过在soLiteralParams中启用soLiteralParamsTHttpRio.Converter.Options 。 这告诉Delphi不要像你看到的那样“解开”参数。 “文档”方面是Delphi WSDL导入程序通常可以解决的问题,因此您不必担心这一点。

另一种解决方案是告诉WCF服务使用RPC /编码样式,您可以通过向服务添加以下属性来实现:

 [ServiceContract] [XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded)] public interface IMyService { // etc. } 

第二个是不推荐的,因为正如我之前提到的,RPC / Encoded不符合WS-I,但是大多数SOAP工具包都能识别它,所以我在这里列出它是一种可能性。

我刚刚做了其中一个,最后我进行了一系列的stringreplace调用来改变我的XML输出,以去除内联命名空间并使其看起来像SoapUI的格式。 是的,需要大量手动黑客才能做到这一点。

例如:

创建RIO后,调用自己的BeforeExecute proc:

 ... EEUPSERTRIO.OnBeforeExecute := self.RIO_BeforeExecute; ... procedure TMyWrapper.RIO_BeforeExecute(const MethodName: string; var SOAPRequest: WideString); { Since Delphi isn't very good at SOAP, we need to fix the request so that the namespaces are correct. Basically, you take what Delphi gives you and try it in SoapUI. If yours doesn't work and SoapUI's version does, make yours look like theirs. } 

…现在删除内联命名空间:

 SOAPRequest := StringReplace(SOAPRequest,' xmlns:NS1="http://services.xxx.de/xxx"','',[rfReplaceAll,rfIgnoreCase]); 

……很多这些。

然后,您将使用包含所需命名空间的soap标头替换soap标头。

 SOAPRequest := StringReplace(SOAPRequest,'xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"','xmlns:ns1="http://services.xyzcorp.com/xyz/EnterpriseEmployeeService_1_0" '+'xmlns:ns1="http://schemas.xyzcorp.com/TLOIntegration_HRO_Preview/TLOIntegration_1_0" ',[]); 

然后你可以重新注入好的:

  ReplaceTag(SOAPRequest,'','ns1:'); ReplaceTag(SOAPRequest,'','ns1:'); ReplaceTag(SOAPRequest,'','ns1:'); 

最后,您可以通过使用SoapUI重新使用WSDL并让它托管模拟服务来轻松捕获您的Delphi输出。 然后将您的应用指向它作为端点,它将捕获输出。
或者,您可以使用Fiddler作为代理来捕获请求。

Delphi和Java框架使用不同的名称空间。 如果兼容的一种方法是拦截原始xml并将所有“NS2”更改为反序列化程序所期望的任何内容

干杯