开发者

Delphi SOAP arrays problem

开发者 https://www.devze.com 2023-03-27 02:07 出处:网络
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 array

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));

fina开发者_StackOverflow社区lization
  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


Thanks to all. All works fine with this code:

Server

Interface part:

interface

const
  IS_OPTN = $0001;
  IS_UNBD = $0002;

type tNoteCollection=class(tremotable)
  private
    fnotes:TnoteStructure;
    procedure Setnotes(Index: Integer; const anotes: TnoteStructure);
  published
    property notes:TnoteStructure index(IS_OPTN or IS_UNBD)  read fnotes write setnotes;
    procedure setlen(count:byte);
    function getlen:integer;
end;

implementation

procedure tNoteCollection.setlen(count:byte);
begin
   setlength(fnotes,count);
end;

function tNoteCollection.getlen:integer;
begin
   result:=length(fnotes);
end;

procedure tNoteCollection.Setnotes(Index: Integer; const anotes: TnoteStructure);
begin
  fnotes:=anotes;
end;

Implementation part:

function Tcis2opus.GetNotes(ClientInformationStructure:TClientInformationStructure)
              : tNoteCollection;
begin
  try
    result:=tNoteCollection.Create;
    result.setlen(1);
    result.notes[0]:=tnote.create;
    result.notes[0].NotetId:=inttostr(random(100));
    result.notes[0].AuthorUserName:='!1!'+ClientInformationStructure.ClientApplicationName;
    result.notes[0].SequenceNumber:=999;
  except
    on e:exception do addtolog(e.Message)
  end;
end;

Client

procedure TForm1.BitBtn1Click(Sender: TObject);
var c:tclientinformationstructure;
    r:tNoteCollection;
begin
  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:=nil;
    r:=(HTTPRIO1 as iCIS2Opus).GetNotes(c);
      if r.getlen>0 then
        if assigned(r.notes[0]) then showmessage(r.notes[0].AuthorUserName);
  finally
    if assigned(c) then freeandnil(c);
    if assigned(r) then freeandnil(r);
  end;
end;


Use SoapUI to send a request and see if anything is in the response. Working with objects is convenient, but sometimes you have to get down into the lower level and see the XML that's actually being sent. SoapUI is your friend here.

0

精彩评论

暂无评论...
验证码 换一张
取 消