· Apr 13, 2018

Creating Manually Soap Request as string

I am trying to created SOAP request body that I need to post as string. I created the SOAP client and tried with this to get SOAP envelope. Can you suggest a way for this.

Set proxy=##Class(Client.Class.Client.Methodname).%New("Methodname")
Set proxy.Para1="a"
Set proxy.Para2="b"
Set tClient=##Class(Client.Class.Client).%New()
Do tClient.WriteHTTPContent(proxy,proxy.%RequestName,0,0,"","",.stream)

Discussion (14)1
Log in or sign up to continue

Not sure exactly what you're trying to do or what problem  you're exactly facing (more details would be helpful) but, assuming you're trying to handle the soap body yourself instead of what the wizard generated then you can create a method to create the body and add the name to the WriteSOAPBodyMethod  property of the client class. It's not recommended to call Cache internal methods in your code. It's better to use any provided "hooks" if available.

To make it more clear, I've a REST service which takes 'SOAP Request' in it's body and forward the request to SOAP endpoint. Now I have to call this service where I need to frame a SOAP envelope. I created the SOAP client and it can call only SOAP service(end point is a class with SOAP webmethod class). But in this case a SOAP envelop needs to be created to pass it to REST's POST.

That makes it more clear, but not easier.

Class  %SOAP.WebClient  is the base for any SOAP Client in Caché.
It has a property Transport to provide a registered class for alternate transport (or no immediate transport in your case)

check the code starting with Method InvokeClient(...
and look for transport within the next 50 lines to see how that works up to here

#; Make the request
Set sc=transport.DoSOAPRequest($this,Action,OneWay,stream,.responseStream)

Just to be clear:
I personally won't do it that way because of all the related maintenance risks.

Well my question has to scoped within object script. Trying to find the way. How about creating the request using  %XML.Writer.

Expected Output for class 'Myclass'

Class User.Myclass

Property Username As %String;

Property Password As %String;

<SOAP-ENV:Envelope xmlns:SOAP-ENV=""
    xmlns:xsi="" xmlns:s="">
        <Myclass xmlns="">

the WRITE is just to visualize the example

the loop in YOUR class could be: 

 for msg=1:1 set msg(msg)=stream.ReadLine() quit:stream.AtEnd 

but that's just standard COS programming. Nothing special. see here
Then you have the local array msg with your SOAP message
Similiar the Try{ } Catch {}  construct that ignores the error that you experience as you don't get a real SOAP response here.

You may create a normal SOAP Client in Studio using the Wizard.

Then you add a transport class to display / dump your request. (example in SAMPLES)

Class SOAPDemo.Transport Extends %RegisteredObject
ClassMethod DoSOAPRequest(
 client As %SOAP.WebClient,
 Action As %String,
 OneWay As %Boolean = 0,
 stream As %FileBinaryStream,
 ByRef responseStream As %GlobalBinaryStream) As %Status

    write !,"**** SOAP Request Begin ****",!
    for  write stream.ReadLine(),! quit:stream.AtEnd
    write !,"**** SOAP Request End ****",!

Example to use it :

SAMPLES>set soap=##class(SOAP.DemoProxy).%New()
SAMPLES>set soap.Transport=##class(SOAPDemo.Transport).%New()  ;; add cusomized transport
SAMPLES>try {write !,soap.Mission() } catch {}    ;; you don't get a reply, so ignore it
**** SOAP Request Begin ****
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='' xmlns:xsi='' xmlns:s=''>  
<SOAP-ENV:Body><Mission xmlns=""></Mission></SOAP-ENV:Body>

**** SOAP Request End ****
SAMPLES>try {write !,soap.AddInteger(17,4) } catch {}
**** SOAP Request Begin ****
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='' xmlns:xsi='' xmlns:s=''>  
<SOAP-ENV:Body><AddInteger xmlns=""><Arg1>17</Arg1><Arg2>4</Arg2></AddInteger></SOAP-ENV:Body>
**** SOAP Request End ****


so you get Envelope + Body well separated