When I create the following structs in a RODL.
- TROMother with only one field ‘Name’ of type string
- TOChild that is a descendent of TROMother with an extra field ‘AdditionalInfo’ of type string
- TROMotherDynArray an array with elements of type TROMother
And on my server side I implement this call:
function TNewService.TestMotherAndChildInOneArray: TROMotherDynArray;
var
Mother: TROMother;
Child: TROChild;
begin
Result := TROMotherDynArray.Create;
Mother := TROMother.Create;
Mother.Name := 'Mom';
Result.Add(Mother);
Child := TROChild.Create;
Child.Name := 'Kid';
Child.AdditionalInfo := 'Some extra info';
Result.Add(Child);
end;
On the client side the following test is implemented:
procedure TClientForm.Button1Click(Sender: TObject);
var
ROResponse: TROMotherDynArray;
begin
ROResponse := (RORemoteService as INewService).TestMotherAndChildInOneArray;
try
Assert(not (ROResponse[0] is TROChild));
**Assert(ROResponse[1] is TROChild); //This test will fail**
finally
ROResponse.Free;
end;
end;
The solution for this issue is a fix in uROXMLSerializer.WriteStruct. Since it is a long procedure, I will focus only on the changes:
if Assigned(obj) then begin
fNode := AddNode(fNode, lName, ArrayElementId <> -1);
if not (xsoSendUntyped in SerializationOptions) then
// if not fIsSimpleTypeExtension then //We need more than just one check
begin
if not fIsSimpleTypeExtension then
{xsiattr :=} AddXMLAttribute(fNode, 'xsi:type', ns_Custom+':'+obj.ClassName, False)
else
AddXMLAttribute(fNode, 'xsi:type', ns_Standard+':'+ fSimpleType, False);
end
else if obj.ClassType <> aClass then
{xsiattr :=} AddXMLAttribute(fNode, 'xsi:type', ns_Custom+':'+obj.ClassName, False)
// else
// AddXMLAttribute(fNode, 'xsi:type', ns_Standard+':'+ fSimpleType, False);
// {xsiattr :=} AddXMLAttribute(fNode, 'xsi:type', ns_Custom+':'+obj.ClassName, False)
// else
// AddXMLAttribute(fNode, 'xsi:type', ns_Standard+':'+ fSimpleType, False);
end
Again, this issue exists in several versions, but also in 9.3.105.1351