More SOAP header questions.
I posted a question on the official boards (https://forums.embarcadero.com/thread.jspa?threadID=117922&tstart=0), and so far it has been …crickets… – but I stumbed upon this post on SO: http://stackoverflow.com/questions/13751289/send-simple-strings-in-soap-header-in-delphi
which shows how to directly override TRemotable.ObjectToSoap to inject structures in the soap header. Unfortunately, it seems to be slightly more tricky to graft this into a WDSL document generated unit (and lose/reintegrate the modifications each time you rebuild from a new WDSL file).
ANY clues to how to do this smarter, would be appreciated.
Why is there no proper Soap Header handling in these classes, I wonder. It seems that the WDSL importer is somewhat outdated, since it refers to SOAP 1.1 and 1.2 – considering 1.2 was renamed 2.0 about 8 years ago.
In addition – another question has arrived: How the heck can I convince it to add _encoding=”utf-8″_ to the XML tag?
I do like learning new stuff, but it can be a hair-tearing experience at times.
http://docwiki.embarcadero.com/Libraries/Seattle/en/Soap.InvokeRegistry.ISOAPHeaders
says “For client-side header support, TRIO implements the ISOAPHeaders interface. However, you can’t obtain an ISOAPHeaders interface directly from a remote interfaced object, because when you try to obtain an interface from TRIO or one of its descendants, it assumes that you are trying to obtain an invokable interface for a server object and generates an in-memory vtable. Instead, you must access the ISOAPHeaders interface from the invokable interface that the remote interface object supports.”
Can someone pretend I am stupid (should not be hard), and explain that last sentence to me?
IMHO this part of the documentation was half-generated, half-obfuscated by the maintainer. I guess it means that you need to use (Service as ISOAPHeaders) instead of directly Service.
But http://docwiki.embarcadero.com/RADStudio/Seattle/en/Processing_Headers_in_Client_Applications sounds easier to understand, I guess.
A. Bouchez That is a lot clearer if you want to “hand code” requests, but it says nada about how to do this on a class hierarchy generated from a wdsl file.
… this is why I like REST so much. The “S”imple in SOAP is not obvious. 😉
SOAP = slippery stuff, for sure…
I guess what I am asking is…
If I want to inject a soap header with a custom block in the ObjectToSOAP method of a TRemotable descendent without “manually” injecting text in the XML – how would I do it?
/sub
Posted a Q at SO:
http://stackoverflow.com/questions/32909061/how-do-i-add-a-custom-soap-header-to-a-soap-invokeregistry-tremotable-object-in
/waitfor
“I do like learning new stuff, but it can be a hair-tearing experience at times.” I fully agree.
Did you get this sorted?
If not please email me at the support address on http://www.pcdata.co.uk but substitute philip for support.
regards
PLJ
Philip Jackson Not yet sorted. Soap header handling seems to be a basic capability not properly handled by the WDSL code generator.
Lars Fosdal is it like String&Replace all over there? 😉
Ilya S I want to avoid that if possible – but the documentation is terse and not very helpful.
Well, it’s not string manipulation, and it looks like shite, but it works.
There must be a cleaner way to do this!?
Instead of having the query soap classes inherit from TRemotable, I made a TGepirQuery that adds
TGepirQuery = class(TRemotable)
private
class var Fcascades: Integer;
class var FGLN: String;
var
FRequestHeader: gepirRequestHeader;
class procedure Setcascades(const Value: Integer); static;
class procedure SetGLN(const Value: String); static;
public
constructor Create; override;
class constructor CreateTGepirResponse;
destructor Destroy; override;
function ObjectToSOAP(RootNode, ParentNode: IXMLNode;
const ObjConverter: IObjConverter;
const NodeName, NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions;
out RefID: InvString): IXMLNode; override;
class property GLN:String read FGLN write SetGLN;
class property cascades: Integer read Fcascades write Setcascades;
property RequestHeader: gepirRequestHeader read FRequestHeader write FRequestHeader;
published
end;
The ObjectToSoap override is a bit hairy…
function TGepirQuery.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const NodeName,
NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;
var
SoapHeader: IXMLNode;
begin
SoapHeader := RootNode.ParentNode.AddChild(‘SOAP-ENV:Header’, 0);
RequestHeader.ObjectToSOAP(RootNode, SoapHeader, ObjConverter, RequestHeader.ClassName, ”, ”,
[ocoDontPrefixNode, ocoDontPutTypeAttr], RefID);
Result := inherited ObjectToSoap(RootNode, ParentNode, objConverter, NodeName, NodeNameSpace, ChildNameSpace, ObjConvOpts, RefID);
end;
and the output is “embellished with” a lot of namespace crap that strictly doesn’t need to be there.