2011-02-23 146 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