2010-03-18 79 views
12

我的工作,提供了一个SOAP接口的系统上。其中一个将使用该接口的系统在Delphi 7中进行了编码。该Web服务使用WCF(基本http绑定,SOAP 1.1)开发。德尔福SOAP信封和WCF

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

这是消息怎么看起来像SOAP UI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.xxx.de/xxx"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <ser:GetCustomer> 
     <!--Optional:--> 
     <ser:GetCustomerRequest> <!-- this is a data contract --> 
      <ser:Id>?</ser:Id> 
     </ser:GetCustomerRequest> 
     </ser:GetCustomer> 
    </soapenv:Body> 
</soapenv:Envelope> 

我不是一个Delphi开发人员,但我开发了一个简单的测试客户端来看看是怎么回事错误。这是德尔福发送的SOAP信封。

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> 
    <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:NS2="http://services.xxx.de/xxx"> 
    <NS1:GetCustomer xmlns:NS1="http://services.xxx.de/xxx"> 
     <GetCustomerRequest href="#1"/> 
    </NS1:GetCustomer> 
    <NS2:GetCustomerRequest id="1" xsi:type="NS2:GetCustomerRequest"> 
     <Id xsi:type="xsd:int">253</Id> 
    </NS2:GetCustomerRequest> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

WCF抛出一个错误是在德语...;)

居wurde DAS结束元素 “身体” 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以这种消息格式工作的方式?任何帮助是极大的赞赏!

+1

问题不在NS1 NS2部分。问题在于德尔福在制造结构上不正确的XML。看来,Web服务期待GetCustomerRequest被嵌套在GETCUSTOMER,但德尔福的客户端没有嵌套GetCustomerRequest元素。我不知道如何解决它。您是否使用WCF服务中的WSDL生成了Delphi客户端? – 2010-03-18 22:17:58

回答

16

相反的是这里有些人似乎在暗示,德尔福不发送无效 SOAP,它只是发送RPC /编码 SOAP。从所有xsi:type属性中很容易识别。 RPC /编码不符合WS-I,但其仍然有效的SOAP。

WCF默认使用SOAP格式,该格式在服务器端根本无法处理,您必须在客户端进行一些调整。

最简单的解决方案是简单地告诉Delphi使用文档/文字风格。你可以在THttpRio.Converter.Options中打开soLiteralParams。这告诉德尔福不要“放松”你所看到的参数。 “文档”方面的东西,德尔福WSDL进口商通常可以弄清楚,所以你不应该需要担心。

另一个解决办法是告诉WCF服务中加入下列属性的服务使用RPC /编码风格,你可以这样做:

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

二是不建议,因为,正如我所说早些时候,RPC/Encoded与WS-I不兼容,但是大多数SOAP工具包都能识别它,因此我将它列为可能。

-1

Delphi和Java框架使用不同的命名空间。做出是否兼容的一种方式是截获的原始XML和更改所有的“NS2”到任何解串器预计

干杯

+0

-1:对符合标准的SOAP解析器,名称空间前缀不是什么问题,所有 – mjn 2010-03-19 11:58:33

3

我只是做了其中的一个,我结束了一系列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]); 

。 .. 很多这些。

然后你就会有一个代替肥皂头包含所需的命名空间。

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,'<metaData>','ns1:'); 
    ReplaceTag(SOAPRequest,'<trackingId>','ns1:'); 
    ReplaceTag(SOAPRequest,'<srcSystem>','ns1:'); 

最后,你可以很容易地通过重新与消耗在了SoapUI WSDL和有它举办mockservice捕捉你的Delphi输出。然后将您的应用程序指向它作为端点,它将捕获输出。
或者,您可以使用Fiddler作为代理来捕获请求。

+0

仅供参考 - 我们使用D2005与D2007的修补程序。 – 2010-03-18 22:02:44

+2

加入德尔福鸡蛋里挑骨头列表... http://stackoverflow.com/questions/2112729/biggest-delphi-nitpicks/2473684#2473684 – 2010-03-18 22:11:17

+0

Thsnks决定。这是一个真正帮助的人 – 2011-06-08 09:29:59