RO:Delphi. Design Flaws in SOAP decoding where the client system is not remobjects

Hello,
I have hit a real show stopper in the soap code. The RO code always assumes that the name-space “http://www.w3.org/2001/XMLSchema-instance” will always be prefixed with ‘xsi:’ this is just not the case and means that clients which do not use the expected xsi prefix will not work correctly when being decoded.

I have reported this issue before and provided a fix where xsi:nil values were not being decoded properly. See the following topic link.
http://talk.remobjects.com/t/soap-nillable-types-in-remobjects-soap-server/357/12?u=will_honor

This fix needs to be taken further so that things like type inheritance work correctly in SOAP. The following snippet decodes as the base abstract class rather than the actual type “JobEventAppointmentReminder” which hides a lot of the fields from the application.

  <JobEvents xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <JobEventAbstract i:type="JobEventAppointmentReminder">
    <ActionID>986360</ActionID>
    <AllocationID>1438975</AllocationID>
    <ExternalEventReference>56789</ExternalEventReference>
    <EventTimestamp>2013-10-22T14:03:31.1996859+01:00</EventTimestamp>
    <AppointmentReference>23</AppointmentReference>
    <AppointmentReminderMethod>armLetter</AppointmentReminderMethod>
    <AppointmentCounter>2</AppointmentCounter>
  </JobEventAbstract>

an example of the incorrect RO code can be found at uROXMLSerializer.BeginReadObject line 1110

clstype :={$IFDEF UNICODE}VarToStr{$ELSE}VarToWideStr{$ENDIF}(fNode.GetAttributeValue('xsi:type', aClass.ClassName));

I really hope you can improve the quality of the soap support in RO. Every time I go near it I end up in hours of debugging and trying to sort out issues seemingly caused by a lack of testing. The usual suspects are very basic support of nillable types (Trying to leave a class nil is almost impossible.) and name-spacing issues caused by prefix assumptions.

Regards,
Will.

(01-Nov-2013 edited to quote the code properly in the new RO:Talk Forums)

The following function seems to resolve the issue. I suggest using this (or something like this) rather than the hard coded name-space prefixes.

function TROXMLSerializer.GetAttributeValue(aNode : IXMLNode ; AttributeName : String; NameSpaceURI : String; DefaultValue : Variant) : Variant ;
var
  i : integer ;
begin
  for I := 0 to aNode.AttributeCount-1 do
  begin
    // note some clients inclue the trailing '/' in the namespace uri so use copy to look for the bulk of the uri.
    if comparetext(NameSpaceURI,copy(aNode.Attributes[i].NamespaceURI,1,length(NameSpaceURI)))=0 then
    if pos(format(':%s',[AttributeName]),aNode.Attributes[i].Name)>0 then
    begin
      Result := aNode.Attributes[i].Value ;
      exit;
    end;
  end;
  result := DefaultValue;
end;

As an example uROXMLSerializer.BeginReadObject line 1110 would change as follows. Of course there are other areas where this change is necessary.

clstype :={$IFDEF UNICODE}VarToStr{$ELSE}VarToWideStr{$ENDIF}(GetAttributeValue(fNode,'type',Namespace_xsi, aClass.ClassName));

Regards,
Will.

(01-Nov-2013 edited to quote the code properly in the new RO:Talk Forums)

Hi,

thank you for report and suggestions, we will fix this issue in near future.