Jeff Sanders Technical Blog

I am a Microsoft employee that has worked on all aspects of the Web Stack for a long time. I hope these blogs are useful to you! Use this information at your own risk.


<< Go Back

How To Send Soap Call Using Msxml Replace Stk

- 14 Jun 2007

I know… This is a simple thing, but there is no documentation on it so here it is:

UPDATE:  You can now use Windows Webservica API (WWSAPI) to create native code WebService calls!

The SoapToolkit (STK) is out of support.  So what if you need to make a SOAP call in VB 6 or scripting?  Realizing that SOAP calls to web service are just a POST with some XML, you should be able to do this easily.  You can get the format for this POST from a network sniffer such as Network Monitor (available from Microsoft) or from the WSDL of service definition.

Here is a simple definition of a web service that returns the length of a string:

GetStringLength

 

Test

The test form is only available for requests from the local machine.

SOAP 1.1

The following is a sample SOAP 1.1 request and response. The placeholders shown need to be replaced with actual values.

POST /HelloWS/service.asmx HTTP/1.1
Host: jsandersvm2003
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/GetStringLength"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetStringLength xmlns="http://tempuri.org/">
      <theString>string</theString>
    </GetStringLength>
  </soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetStringLengthResponse xmlns="http://tempuri.org/">
      <GetStringLengthResult>int</GetStringLengthResult>
    </GetStringLengthResponse>
  </soap:Body>
</soap:Envelope>

Here is one way to make this call in a simple VB form application. Reference MSXML3.0 in your project (beware of lines wrapping in your browser if you are a cut and past programmer).

 

 

 

</p>

Sub

</font></span>

 

</span>

 

Command2_Click()
    ‘How to send this using MSXML
    ‘POST /HelloWS/service.asmx HTTP/1.1
    ‘Host: jsandersvm2003
    ‘Content-Type: text/xml; charset=utf-8
    ‘Content -length: <>
</span> </p>

    ‘SOAPAction: “http://tempuri.org/GetStringLength”

</p>

 

</font></span>

 

</span>

 

    ‘
   
‘<soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>
   

    </span>‘ <GetStringLength xmlns=”http://tempuri.org/”>
   
<></theString>
    </span>‘ </GetStringLength>
   
‘ </soap:Body>
   
</p>

‘</soap:Envelope>

</p>

 

</font></span>

 

</span>

 

    Dim myXML As New

XMLHTTP30</p>

 

</font></span>

 

</span>

 

    ‘ False means Synchronously
   
myXML.open(“POST”, “http://jsandersvm2003/HelloWS/service.asmx”, False)
    myXML.setRequestHeader(
“Content-Type”, “text/xml; charset=utf-8”)
    myXML.setRequestHeader(
“SOAPAction:”, http://tempuri.org/GetStringLength)

</p>


    ‘ NOTE: You could do this… very brute force way to send it.
   
‘Dim theTxt As String
   
‘theTxt = “<soap:Envelope xmlns:xsi=” & Chr(34) & “http://www.w3.org/2001/XMLSchema-instance” & Chr(34) & ” xmlns:xsd=” & Chr(34) & “http://www.w3.org/2001/XMLSchema” & Chr(34) & ” xmlns:soap=” & Chr(34) & “http://schemas.xmlsoap.org/soap/envelope/” & Chr(34) & “><GetStringLength xmlns=” & Chr(34) & “http://tempuri.org/” & Chr(34) & “><theString xmlns=” & Chr(34) & “http://tempuri.org/” & Chr(34) & “>string</theString></GetStringLength></soap:Envelope>”

 

 

 

 

</p>

 

</font></span>

 

</span>

 

    ‘myXML.send theTxt
   

‘ NOTE: This allows you to leverage the XML DOM

</p>

 

</font></span>

 

</span>

 

    Dim node
   
Dim xmlSrcDoc As New MSXML2.DOMDocument30
    xmlSrcDoc.async =
False
   
xmlSrcDoc.validateOnParse = False
   
xmlSrcDoc.resolveExternals = False
   
xmlSrcDoc.preserveWhiteSpace = True
    
‘ caveat for the createProcessingInstruction. the encoding string will be missing from the XML instruction line.
   
‘ so you could skip the createProcessingInstruction code, instead prepend the string to the XML you generate for the rest of the body ala 
    ‘

“myXML.send “ ” & xmlSrcDoc.xml

</p>

 

</font></span>

 

</span>

 


    ‘ most servers will not care about that because the HTTP header already specifies the encoding
   
‘ Create a processing instruction targeted for xml.
    node = xmlSrcDoc.createProcessingInstruction(
“xml”, “version=’1.0′”)
   
‘ issue: cannot do this: node.setAttribute “encoding”, “utf-8”
   
xmlSrcDoc.appendChild(node)
    node =
Nothing
    
‘ Create the Soap Envelope
   
Dim soapEnvelope As IXMLDOMElement
    soapEnvelope = xmlSrcDoc.createElement(
“soap:Envelope”)
   
‘ Create the attributes for it
   
soapEnvelope.setAttribute(“xmlns:soap”, “http://schemas.xmlsoap.org/soap/envelope/”)
    soapEnvelope.setAttribute(
“xmlns:xsi”, “http://www.w3.org/2001/XMLSchema-instance”)
    soapEnvelope.setAttribute(
“xmlns:xsd”, “http://www.w3.org/2001/XMLSchema”)
    xmlSrcDoc.appendChild(soapEnvelope)
   
‘ Create the Soap Body
   
Dim soapBody As IXMLDOMElement
    soapBody = xmlSrcDoc.createElement(
“soap:Body”)
    soapEnvelope.appendChild(soapBody)
   
‘ Create the node for the call we are making
   
Dim soapCall As IXMLDOMElement
    soapCall = xmlSrcDoc.createElement(
“GetStringLength”)
    soapCall.setAttribute(
“xmlns”, “http://tempuri.org/”)
    soapBody.appendChild(soapCall)
   
‘ finally add the argument(s)
   
Dim soapArgs As Object
   
soapArgs = xmlSrcDoc.createElement(“theString”)
    soapArgs.Text =
“Jeff is cool”
   
soapCall.appendChild(soapArgs)
   
‘ let it go!
   
myXML.send(xmlSrcDoc.xml)
   
‘ myXML.send “ ” & xmlSrcDoc.xml
   
Dim xmlDoc As MSXML2.DOMDocument30
    xmlDoc = myXML.responseXML
   
‘ This query will depend on what you expect back from the SOAP call
   

MsgBox(xmlDoc.Text)</p>

 

</font></span>

 

</span>

 

    ‘ or this if you want to traverse the XML DOM
   
‘Dim oNode As Object
   
‘Set oNode = xmlDoc.documentElement.selectSingleNode(“//HelloWorldResult”)
   
‘If oNode Is Nothing Then
   
‘     MsgBox “Requested information not found.”
   
‘Else
   
‘     MsgBox oNode.Text
   

‘End If

</p>

End

</font></span>

 

</span>

 

Sub

</p>

 

<< Go Back