2010-03-18 105 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