I have a SOAP application created with delphi.
Input comes to server correct. But output is always empty. r
object (response) created, but length(r.notes)
always 0. If I do application without arrays, it also works correct. Where is the problem? 3 days of googling and trying different combinatios did not help.
Interface:
////////////// INPUT ///////////////////////
type TClientInformationStructure= class(TRemotable)
private
fClientApplicationName:string;
fClientApplicationPassword:string;
fRequestIdentifier:string;
fStartSequenceNumber:integer;
fNumberOfNotes:integer;
published
property ClientApplicationName:string read fClientApplicationName write fClientApplicationName; //Name of calling application
property ClientApplicationPassword:string read fClientApplicationPassword write fClientApplicationPassword; //Password that calling application must use to call the service
property RequestIdentifier:string read fRequestIdentifier write fRequestIdentifier;//Transaktionsid from calling system that is stamped in all loggings for service,
//so that later it is easy to compare client and server logs. May be null.
property StartSequenceNumber:integer read fStartSequenceNumber write fStartSequenceNumber;
property NumberOfNotes:integer read fNumberOfNotes write fNumberOfNotes;
end;
///////////// OUTPUT ////////////////////////////
Type TNote=class(tremotable)
private
fNotetId:string;
fSequenceNumber:integer;
fDeleteMark:boolean;
fAuthorRole:string;
fAuthorUserName:string;
fAuthor:string;
fAcceptTime:tdateTime;
fOrganizationalUnit:string;
fLocationStartTime:tdateTime;
fLocationEndTime:TdateTime;
fBeadWard:string;
fPersonCivilRegistrationIdentifier:string;
fNoteType:string;
fNoteText:string;
fMoreNotesAvailable:boolean;
public
property NotetId:string read fNotetId write fNotetId;
property SequenceNumber:integer read fSequenceNumber write fSequenceNumber;
property DeleteMark:boolean read fDeleteMark write fDeleteMark;
property AuthorRole:string read fAuthorRole write fAuthorRole;
property AuthorUserName:string read fAuthorUserName write fAuthorUserName;
property Author:string read fAuthor write fAuthor;
property AcceptTime:tdateTime read fAcceptTime write fAcceptTime;
property OrganizationalUnit:string read fOrganizationalUnit write fOrganizationalUnit;
property LocationStartTime:tdateTime read fLocationStartTime write fLocationStartTime;
property LocationEndTime:TdateTime read fLocationEndTime write fLocationEndTime;
property BeadWard:string read fBeadWard write fBeadWard;
property PersonCivilRegistrationIdentifier:string read fPersonCivilRegistrationIdentifier write fPersonCivilRegistrationIdentifier;
property NoteType:string read fNoteType write fNoteType;
property NoteText:string read fNoteText write fNoteText;
property MoreNotesAvailable:boolean read fMoreNotesAvailable write fMoreNotesAvailable;
end;
type TnoteStructure = array of TNote;
type tNoteCollection=class(tremotable)
private
fnotes:TnoteStructure;
public
property notes:TnoteStructure read fnotes write fnotes;
end;
type
ibla = interface(IInvokable)
['{FFD831EC-56B1-4C0E-9CCE-8D9C7ECEE656}']
function GetNotes(ClientInformationStructure:TClientInformationStructure)
: tNoteCollection; stdcall;
end;
implementation
initialization
RemClassRegistry.RegisterXSClass(TClientInformationStructure);
RemClassRegistry.RegisterXSClass(Tnote);
RemClassRegistry.RegisterXSClass(tNoteCollection);
RemClassRegistry.RegisterXSInfo(TypeInfo(TnoteStructure));
InvRegistry.RegisterInterface(TypeInfo(ibla));
finalization
RemClassRegistry.UnRegisterXSClass(TClientInformationStructure);
RemClassRegistry.unRegisterXSClass(Tnote);
RemClassRegistry.unRegisterXSClass(tNoteCollection);
RemClassRegistry.unRegisterXSInfo(TypeInfo(TnoteStructure));
InvRegistry.UnRegisterInterface(TypeInfo(ibla));
end.
Implementation:
type
Tbla = class(TInvokableClass, ibla)
public
function GetNotes(ClientInformationStructure:TClientInformationStructure)
: TNotecollection; stdcall;
end;
implementation
function Tbla.GetNotes(ClientInformationStructure:TClientInformationStructure)
: TNotecollection;
var n:tNoteStructure;
begin
try
result:=TNotecollection.Create;
setlength(n,1);
n[0]:=tnote.create;
n[0].NotetId:=inttostr(random(100));
n[0].AuthorUserName:='!1!'+ClientInformationStructure.ClientApplicationName;
n[0].SequenceNumber:=999;
result.notes:=copy(n);
except
on e:exception do addtolog(e.Message)
end;
end;
initialization
InvRegistry.RegisterInvokableClass(Tbla)
finalization
InvRegistry.unRegisterInvokableClass(Tbla)
Client side:
c:=tclientinformationstructure.Create;
try
c.ClientApplicationName:=labelededit1.Text;
c.ClientApplicationPassword:=labelededit2.Text;
c.RequestIdentifier:=labelededit3.Text;
c.StartSequenceNumber:=strtointdef(labelededit4.Text,0);
c.NumberOfNotes:=strtointdef(labelededit5.Text,0);
r:=(HTTPRIO1 as ibla).GetNotes(c);
if assigned(r) then
if length(r.notes)>0 then
if assigned(r.notes[0]) then showmessage(r.notes[0].AuthorUserName);
finally
freeandnil(c);
if assigned (r.notes[0]) then freeandnil(r.notes[0]);
if assigned(r) then freeandnil(r);
end;
In the Server, to go to the SOAP web module, select the HTTPSoapPascalInvoker component, and open up the Options property in the Object Inspector. Make sure the option "soRootRefNodesToBody" is checked. That will ensure that in the SOAP resonse, the elements are passed outside of the response node, in the body, where the client can find them.
Groetjes, Bob Swart
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With