【问题标题】:Delphi SOAP arrays problemDelphi SOAP 数组问题
【发布时间】:2011-08-12 18:54:30
【问题描述】:

我有一个用 delphi 创建的 SOAP 应用程序。

输入正确到达服务器。但是输出总是空的。 r 对象(响应)已创建,但 length(r.notes) 始终为 0。如果我在没有数组的情况下执行应用程序,它也可以正常工作。问题出在哪里? 3 天的谷歌搜索和尝试不同的组合没有帮助。

界面:

////////////// 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.

实施

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)

客户端:

  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;

【问题讨论】:

  • 尝试RegisterSerializeOptions,如answer中所述。
  • TOndrej:完成,没有帮助。试图使数组类型不是属性而是函数结果。在这种情况下,客户端得到了长度正确的数组,创建了对象,但所有对象的字段都是空的或 0。
  • 回复是这样的:<SOAP-ENV:Body xmlns:NS1="urn:Intf"> <GetNotesResponse xmlns="urn:Intf-icis2opus"> <NS1:return/> <NS1:return/> </GetNotesResponse> </SOAP-ENV:Body>

标签: arrays delphi soap


【解决方案1】:

在服务器中,要转到 SOAP Web 模块,选择 HTTPSoapPascalInvoker 组件,然后在 Object Inspector 中打开 Options 属性。确保选中“soRootRefNodesToBody”选项。这将确保在 SOAP 响应中,元素被传递到响应节点之外的主体中,客户端可以在其中找到它们。

格罗耶斯,鲍勃·斯沃特

【讨论】:

    【解决方案2】:

    谢谢大家。 这段代码一切正常:

    服务器

    接口部分:

    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;
    

    实现部分:

    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;
    

    客户

    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;
    

    【讨论】:

    • 不要让我们发现差异。说明您必须更改哪些部分才能使您的程序正常运行。
    • 此注释准确显示了更改。看看接口部分如何声明数组并实现添加项的方法
    • result:=tNoteCollection.Create 但谁解除了这个分配?是不是因为它是可动的,所以调用后就被销毁了?
    • 次要:freeandnil不需要指定检查,因为free在调用destroy之前明确检查对象是否为nil。
    【解决方案3】:

    使用 SoapUI 发送请求并查看响应中是否有任何内容。使用对象很方便,但有时您必须深入到较低级别并查看实际发送的 XML。 SoapUI 是你的朋友。

    【讨论】:

    • 克里斯,感谢您的回答。我安装了 SOAPUI。我得到了响应 但我不知道这是什么意思。看起来响应只有指向对象的指针...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多