I need to send something like this:
<soapenv:Header>
<ser:userName>admin</ser:userName>
<ser:userPassword>secret</ser:userPassword>
</soapenv:Header>
Delphi WSDL importer, generated this:
userName2 = class(TSOAPHeader)
private
FValue: string;
published
property Value: string read FValue write FValue;
end;
userName = type string;
WsService = interface(IInvokable)
function call(const userName: userName; const userPassword: userPassword);
and registered the type as:
InvRegistry.RegisterHeaderClass(TypeInfo(WsService), userName2, 'userName', 'http://localhost/path/to/services');
The problem is that when I call it using the delphi generated code it puts the userName and password in the Body section of the SOAP message, not in the Header.
So I tried sending the Headers myself, like this:
Changed the type definition to inherit from the userName2 class because I can't send a string using the ISOAPHeaders.Send() method.
userName = class(userName2);
Then sent the headers:
user := userName.Create;
user.Value := 'admin';
WS := GetWsService;
(WS as ISOAPHeaders).Send(user);
Now the headers are in the correct place, but they are being sent like this:
<SOAP-ENV:Header>
<NS1:userName xmlns:NS1="http://localhost/path/to/services">
<Value xmlns="http://localhost/path/to/services">admin</Value>
</NS1:userName>
</SOAP-ENV:Header>
Almost there, but I don't want the "Value" property, I just want a plain simple tag in the header.
How can I do it?
Thanks.
== EDIT ==
As requested, the WSDL is here: http://desenvolvimento.lemontech.com.br:8081/wsselfbooking/WsSelfBookingService?wsdl
SOAP UI imported it and generated this sample request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://lemontech.com.br/selfbooking/wsselfbooking/services">
<soapenv:Header>
<ser:userPassword></ser:userPassword>
<ser:userName></ser:userName>
<ser:keyClient></ser:keyClient>
</soapenv:Header>
<soapenv:Body>
<ser:pesquisarSolicitacao>
<!--You have a CHOICE of the next 2 items at this level-->
<idSolicitacaoRef></idSolicitacaoRef>
<dataInicial></dataInicial>
<dataFinal></dataFinal>
<registroInicial>1</registroInicial>
<!--Optional:-->
<quantidadeRegistros>50</quantidadeRegistros>
</ser:pesquisarSolicitacao>
</soapenv:Body>
</soapenv:Envelope>
This sample request works just fine, but I can't figure out how to make this call in Delphi.
You can override the serialization for any
TSOAPHeader
class. Just override itsObjectToSOAP
function. I came up with this:results in this request header:
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.
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:
Then register this header:
And send the Header manually:
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:
Source: http://docwiki.embarcadero.com/RADStudio/XE3/en/Using_Remotable_Objects