2011-02-23 152 views
2

當我用我的客戶端調用SOAP方法時,我有一個非常有趣的問題,我必須傳遞一個類型爲Array_Of_Int(Array_Of_Int = Integer數組)的參數,問題是當數組正在在請求生成,它會生成以下在SOAP客戶端的Array_Of_Int

<ArrayParam> 
    <item>12345</item> 
    <item>23456</item> 
    <item>34567</item> 
</ArrayParam> 

,但我相信,服務器預期

<ArrayParam>12345</ArrayParam> 
<ArrayParam>23456</ArrayParam> 
<ArrayParam>34567</ArrayParam> 

我敢肯定,德爾福有莫名其妙的RegisterSerializeOptions或RegisterInvokeOptions針對此問題的解決辦法,但是我似乎無法找到問題,想法?

謝謝大家的時間,我用Delphi 2010

編輯:爲了解決這個問題,因爲布諾提到的,我們必須產生的初始化部分添加以下代碼。 PAS文件:

InvRegistry.RegisterInvokeOptions(TypeInfo(<ServerInterfaceNameHere>), ioDocument);

然而強加的另一個問題,命名空間,作爲一個快速,漂亮優雅的修復,我已經添加在THTTPRIO的OnBeforeExecute方法如下代碼

procedure TMyDataModule.MyRioBeforeExecute(const MethodName: string; SOAPRequest: TStream); 

    procedure FixNamespaces; 
    var 
    LStrings: TStringList; 
    begin 
    LStrings := TStringList.Create; 
    try 
     SOAPRequest.Position := 0; 
     LStrings.LoadFromStream(SOAPRequest); 
     SOAPRequest.Position := 0; 
     SOAPRequest.Size := 0; 
     LStrings.Text := StringReplace(LStrings.Text, MethodName, 'NS1:' + MethodName, [rfReplaceAll]); 
     LStrings.Text := StringReplace(LStrings.Text, MethodName + ' xmlns', MethodName + ' xmlns:NS1', []); 
     LStrings.SaveToStream(SOAPRequest); 
     SOAPRequest.Position := 0; 
    finally 
     FreeAndNil(LStrings); 
    end; // tryf 
    end; // procedure FixNamespaces; 

begin 
    FixNamespaces; 
end; 

以上是只是修復,我真希望我能找到一個更清潔,優雅的解決這個問題,如果有誰知道,請確實張貼你的答案

回答

1

由於無人問津張貼自己的答案或者對如何解決這個問題,沒有別的想法,我只是張貼我的修補程序,直到其他人可以有更多的問世優雅的解決方案比編輯請求。

確保下一行代碼被添加到*的初始化部分。當您導入的WSDL文件(非常感謝布諾指出了這一點)

InvRegistry.RegisterInvokeOptions(TypeInfo(<ServerInterfaceNameHere>), ioDocument);

然而強加的另一個問題,命名空間,作爲一個快速,漂亮優雅的修復生成PAS文件,我已經添加了以下代碼在THTTPRio的OnBeforeExecute方法

procedure TMyDataModule.MyRioBeforeExecute(const MethodName: string; SOAPRequest: TStream); 

    procedure FixNamespaces; 
    var 
    LStrings: TStringList; 
    begin 
    LStrings := TStringList.Create; 
    try 
     SOAPRequest.Position := 0; 
     LStrings.LoadFromStream(SOAPRequest); 
     SOAPRequest.Position := 0; 
     SOAPRequest.Size := 0; 
     LStrings.Text := StringReplace(LStrings.Text, MethodName, 'NS1:' + MethodName, [rfReplaceAll]); 
     LStrings.Text := StringReplace(LStrings.Text, MethodName + ' xmlns', MethodName + ' xmlns:NS1', []); 
     LStrings.SaveToStream(SOAPRequest); 
     SOAPRequest.Position := 0; 
    finally 
     FreeAndNil(LStrings); 
    end; // tryf 
    end; // procedure FixNamespaces; 

begin 
    FixNamespaces; 
    // other possible issue to be fixed -- if any 
end; 
+1

我不能確認沒有看到WSDL /架構,但基於你已發佈的修復,該服務可能期望請求/響應的命名空間不同於接口的命名空間。只有通過'RequestNS'和'ResponseNS'屬性才能將此支持添加到Delphi/XE中,進口商將在這些情況下爲每種方法生成該屬性。在Delphi XE之前,唯一的方法是通過BeforeExecute事件(如上所述)或通過在不同名稱空間中註冊接口。如果一個方法預期ns1而另一個預期ns2,則後者不起作用。 – BruneauB 2011-02-25 18:09:55

+0

我真的很失望,因爲我們沒有靈活性(IMO)就如何提出SOAP請求,例如,如果某些屬性,註冊等將來可以解決,我不希望手動執行如此微不足道的操作下一個德爾福版本XE2,超級XE)我將需要至少審查每一個請求,以確保它的工作正常(這在某種程度上反對RAD的想法...),此外,我不會感到驚訝,如果支持將下降明年發佈...反正客戶對WSDL非常嚴格(不能公開[!])。非常感謝您支持Bruneau。 – ComputerSaysNo 2011-02-25 20:35:14

+1

我同意你關於缺乏靈活性。將SOAP綁定到RTTI的最初計劃是基於SOAP編碼規則進行的。隨着標準切換到XML編碼,很明顯這是一個不幸的決定,因爲XML編碼比RTTI編碼需要更多的靈活性/定製: – BruneauB 2011-02-25 21:49:26

4

您描述的兩個序列化選項都是有效的和必需的。問題在於,從語言/原生的角度來看,Delphi使用動態數組(Array_Of_Int = Integer數組)表示他們兩個人。因此,必須告訴運行時是否序列化爲「Pure Collection」(第一種元素和外部ArrayParam)或「無界元素」(「ArrayParam」元素)。

在早期版本中,包括2010年,你可以指示運行時序列化有以下登記爲無界的元素:

RemClassRegistry.RegisterSerializeOptions(TypeInfo(Array_Of_Int), [xoInlineArrays]); 

如果類型是在屬性中使用,你也可以簡單地標記屬性本身如無界的,如:

property propName: Array_Of_Int Index (IS_UNBD) read FName write FName; 

登記方法的缺點在於,它不允許一個(重新)使用兩個序列化的類型。在德爾福XE中,這已得到解決,現在該類型從未註冊過特定的方案。相反,每個動態數組屬性或參數指定它是「純集合」還是「無限元素」,從而不需要爲每個序列化設置不同的動態整數數組。

乾杯,

布諾

+0

我應該補充說,WSDL導入器應該已經生成了必要的'RegisterSerializeOptions'調用。我只看了一下D2010的測試結果,發現導入下列WSDL(https://adwords.google.com/api/adwords/v13/CampaignService?wsdl)時導入器正確生成了:「RemClassRegistry.RegisterSerializeOptions(TypeInfo( Array_Of_int),[xoInlineArrays]);「。如果您有一個進口商未能這樣做的WSDL,請告訴我們(或在qc.embarcadero.com上打開一份報告)。謝謝。 – BruneauB 2011-02-23 15:20:18

+0

再次感謝Bruneau爲您提供幫助的興趣,同時在導入WSDL時添加了xoInlineArrays序列化選項,但由於某些原因,它不會生成預期結果,整個問題是對於數組中的每個項目,delphi生成這是令人沮喪的,因爲到目前爲止我無法解決它,我的死亡線與每個小時更接近:(想法?謝謝 – ComputerSaysNo 2011-02-23 15:29:43

+0

忘了提及SOAP服務是用Java編寫的... – ComputerSaysNo 2011-02-23 15:37:47