Send simple strings in SOAP Header in Delphi

前端 未结 3 1604
灰色年华
灰色年华 2021-02-08 01:49

I need to send something like this:

   
      admin
      secret

        
相关标签:
3条回答
  • 2021-02-08 01:59

    You can override the serialization for any TSOAPHeader class. Just override its ObjectToSOAP function. I came up with this:

    unit Unit16;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, WsSelfBookingService, StdCtrls,
      InvokeRegistry, SOAPHTTPClient, opCOnvertOptions, XMLIntf, XSBuiltIns;
    
    type
      TForm1 = class(TForm)
        Memo2: TMemo;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    type
     TSOAPCredentials = class(TSoapHeader)
     private
        FPassword: string;
        FUsername: string;
        FKeyClient: string;
     public
       function ObjectToSOAP(RootNode, ParentNode: IXMLNode;
                                const ObjConverter: IObjConverter;
                                const NodeName, NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions;
                                out RefID: InvString): IXMLNode; override;
     published
       property userName     : string read FUsername write Fusername;
       property userPassword : string read FPassword write FPassword;
       property keyClient : string read FKeyClient write FKeyClient;
     end;
    
    
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    { TSOAPCredentials }
    
    function TSOAPCredentials.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const NodeName,
      NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;
    begin
     Result := ParentNode.AddChild('userName');
     Result.Text := FUsername;
     Result := ParentNode.AddChild('userPassword');
     Result.Text := FPassword;
     Result := ParentNode.AddChild('keyClient');
     Result.Text := FKeyClient;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    
    var
     ws   : WsSelfBooking;
     Req  : pesquisarSolicitacao;
     Resp : pesquisarSolicitacaoResponse;
     Rio  : THTTPRIO;
     Cred : TSOAPCredentials;
    
    begin
     Rio := THttpRIO.Create(nil);
     ws := GetWsSelfBooking(false, '', Rio);
     Cred := TSOAPCredentials.Create;
     Cred.userName := 'admin';
     Cred.userPassword := 'secret';
     Cred.keyClient := 'key';
     Rio.SOAPHeaders.Send(cred);
     Req := pesquisarSolicitacao.Create;
     Req.registroInicial := 1;
     Req.quantidadeRegistros := 50;
     Resp := ws.pesquisarSolicitacao(Req);    
    end;
    
    end.
    

    results in this request header:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Header>
     <SOAP-ENV:userName>admin</SOAP-ENV:userName>
     <SOAP-ENV:userPassword>secret</SOAP-ENV:userPassword>
     <SOAP-ENV:keyClient>key</SOAP-ENV:keyClient>
    </SOAP-ENV:Header>
    
    0 讨论(0)
  • 2021-02-08 02:10

    You can inject the tags by using a stringreplace on the XML string right before it goes out the door "onto the wire". You need a RIO_BeforeExecute handler, and you can then deal with the SOAPRequest directly.

    0 讨论(0)
  • 2021-02-08 02:16

    Solution:

    It wasn't much obvious, but I just had to add the IS_TEXT value to the Index and declare a new TSOAPHeader descendant, the solution was like this:

    const
      IS_TEXT = $0020;
    
    type
      TSimpleHeader = class(TSOAPHeader)
      private
        FValue: string;
      published
        property Value: string Index (IS_TEXT) read FValue write FValue;
      end;
    
      userName = class(TSimpleHeader);
    

    Then register this header:

    InvRegistry.RegisterHeaderClass(TypeInfo(WsService), userName, 'userName', 'http://localhost/path/to/services');
    

    And send the Header manually:

        User := userName.Create;
        User.Value := 'username';
    
        (WS as ISOAPHeaders).Send(User);
    

    Basically, the IS_TEXT value in the Index prevents Delphi from creating a userName tag and a Value tag inside it. It just places the string of the Value property inside the userName tag.

    It's sad that the Index keywork is used for something so not obvious, also the documentation about it is difficult to find and hard to understand:

    The AS_ATTRIBUTE feature has been deprecated. It still works for legacy code, but the preferred approach is to use the index value of a property. The index property allows you to specify whether a property is an attribute, an unbounded element, an optional element, a text value, or can have a value of NULL.

    Source: http://docwiki.embarcadero.com/RADStudio/XE3/en/Using_Remotable_Objects

    0 讨论(0)
提交回复
热议问题