Array_Of_Int in SOAP Client

I have a very interesting problem, when I call the SOAP method with my client, I have to pass a parameter that is of type Array_Of_Int (Array_Of_Int = array Integer), the problem is that when the array is generated in the request, it generates the following

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

but I suppose the server is expecting

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

I'm sure Delphi has a workaround for this problem somehow in RegisterSerializeOptions or RegisterInvokeOptions, but I can’t find the problem, thoughts ?!

Thank you all for your time, I am using Delphi 2010.

EDIT: To fix this problem, as Brunau mentioned, we need to add the following code to the initialization section of the generated .pas file:

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

However, this poses another problem, the namespace, as a quick and fairly elegant fix, I added the following code in the THTTPRio OnBeforeExecute method

 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; 

The above solution is simple , I really hope that I can find a much cleaner and more elegant solution to this problem, if anyone knows , please post your answer .

+2
source share
2 answers

Since no one cares to post their answer or has any other idea on how to fix this problem, I will simply post my fix until others can come up with a more elegant solution than editing the request.

Make sure the following line of code is added in the initialization section of the * .pas file generated when importing the WSDL file (many thanks to Bruneau for pointing this out)

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

However, this poses another problem, the namespace, as a quick and fairly elegant fix, I added the following code in the THTTPRio OnBeforeExecute method

 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
source

The two serialization options that you described are valid and necessary. The problem is that from a language / native point of view, Delphi represents both of them with a dynamic array (Array_Of_Int = array Integer). So, at runtime, you need to say whether to serialize for the "clean collection" (first view with elements and an external ArrayParam array) or "unlimited elements" ("ArrayParam" elements).

In earlier versions, including in 2010, you could instruct the runtime to serialize as unlimited elements with the following registration:

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

If the type is used in a property, you can also just mark the property itself as unlimited, for example:

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

The drawback of the registration approach is that it does not allow one type to be used for both serializations. This has been fixed in Delphi XE, and now the type is never registered for a particular schema. Instead, each Dynamic Array property or parameter indicates whether it is a Clean Collection or an Unlimited Element, eliminating the need for a separate dynamic array of integers for each serialization.

Greetings

Bruno

+4
source

All Articles