Sending a 'application/soap+xml' SOAP request using Classic ASP

Learn sending a 'application/soap+xml' soap request using classic asp with practical examples, diagrams, and best practices. Covers soap, asp-classic, msxml development techniques with visual expla...

Sending 'application/soap+xml' Requests with Classic ASP

Classic ASP code interacting with a SOAP web service, showing XML and HTTP communication

Learn how to construct and send SOAP 1.2 requests using MSXML2.ServerXMLHTTP in Classic ASP, including XML payload creation and error handling.

Classic ASP, while an older technology, is still in use for many legacy systems. Interacting with modern web services, especially those using SOAP 1.2 with the application/soap+xml content type, can be a challenge. This article will guide you through the process of creating the necessary XML payload, setting up the MSXML2.ServerXMLHTTP object, and sending the request to a SOAP endpoint.

Understanding SOAP 1.2 and application/soap+xml

SOAP (Simple Object Access Protocol) is a messaging protocol specification for exchanging structured information in the implementation of web services. SOAP 1.2 introduced the application/soap+xml media type, which is distinct from the older text/xml used by SOAP 1.1. This distinction is crucial for web service compatibility.

When sending a SOAP 1.2 request, your HTTP Content-Type header must be set to application/soap+xml. Additionally, the XML payload itself needs to adhere to the SOAP 1.2 envelope structure, which includes namespaces for the envelope, encoding style, and potentially the body. The Action header, which specifies the intent of the SOAP request, is also typically included.

sequenceDiagram
    participant Client as Classic ASP Client
    participant Server as SOAP Web Service

    Client->>Server: HTTP POST Request
    Note over Client,Server: Content-Type: application/soap+xml
    Client->>Server: SOAP 1.2 Envelope (XML Payload)
    Server-->>Client: HTTP 200 OK (or error)
    Server-->>Client: SOAP 1.2 Response (XML Payload)

Sequence diagram of a Classic ASP client sending a SOAP 1.2 request to a web service.

Constructing the SOAP 1.2 XML Payload

The core of any SOAP request is its XML payload. For SOAP 1.2, this involves a specific structure. You'll typically use the MSXML2.DOMDocument object in Classic ASP to build this XML programmatically. This approach offers better control and avoids issues with string concatenation for complex XML.

Here's a typical structure for a SOAP 1.2 request envelope:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header/>
  <soap:Body>
    <m:YourMethodName xmlns:m="http://your-namespace.com/your-service">
      <m:Parameter1>Value1</m:Parameter1>
      <m:Parameter2>Value2</m:Parameter2>
    </m:YourMethodName>
  </soap:Body>
</soap:Envelope>

Example SOAP 1.2 XML payload structure.

Sending the Request with MSXML2.ServerXMLHTTP

The MSXML2.ServerXMLHTTP object is the preferred choice for making HTTP requests from Classic ASP, especially in server-side environments, as it offers better security and functionality compared to MSXML2.XMLHTTP. You'll need to set the appropriate headers, including Content-Type and SOAPAction (though SOAPAction is technically optional for SOAP 1.2, many services still expect it).

Below is a comprehensive example demonstrating how to create the XML, set headers, send the request, and process the response.

<%@ Language=VBScript %>
<% Option Explicit %>
<% 
Dim objXMLDoc, objXMLHttp
Dim strURL, strSOAPAction, strRequestXML, strResponseXML
Dim strMethodNamespace, strMethodName

' --- Configuration ---
strURL = "http://your-soap-service.com/Service.asmx"
strMethodNamespace = "http://your-namespace.com/your-service"
strMethodName = "YourMethodName"
strSOAPAction = strMethodNamespace & "/" & strMethodName ' Often required, even for SOAP 1.2

' --- 1. Create the XML Payload ---
Set objXMLDoc = Server.CreateObject("MSXML2.DOMDocument.6.0")
objXMLDoc.async = False
objXMLDoc.preserveWhiteSpace = False

' Create SOAP Envelope
Dim objEnvelope, objHeader, objBody, objMethod
Set objEnvelope = objXMLDoc.createNode(1, "soap:Envelope", "http://www.w3.org/2003/05/soap-envelope")
objXMLDoc.appendChild objEnvelope

Set objHeader = objXMLDoc.createNode(1, "soap:Header", "http://www.w3.org/2003/05/soap-envelope")
objEnvelope.appendChild objHeader

Set objBody = objXMLDoc.createNode(1, "soap:Body", "http://www.w3.org/2003/05/soap-envelope")
objEnvelope.appendChild objBody

' Create Method Node
Set objMethod = objXMLDoc.createNode(1, "m:" & strMethodName, strMethodNamespace)
objBody.appendChild objMethod

' Add Parameters
Dim objParam1, objParam2
Set objParam1 = objXMLDoc.createNode(1, "m:Parameter1", strMethodNamespace)
objParam1.text = "Value1"
objMethod.appendChild objParam1

Set objParam2 = objXMLDoc.createNode(1, "m:Parameter2", strMethodNamespace)
objParam2.text = "Value2"
objMethod.appendChild objParam2

strRequestXML = objXMLDoc.xml

Response.Write "<h2>Request XML:</h2>"
Response.Write "<pre>" & Server.HTMLEncode(strRequestXML) & "</pre>"

' --- 2. Send the HTTP Request ---
Set objXMLHttp = Server.CreateObject("MSXML2.ServerXMLHTTP.6.0")
objXMLHttp.Open "POST", strURL, False ' False for synchronous call

' Set Headers
objXMLHttp.setRequestHeader "Content-Type", "application/soap+xml; charset=utf-8"
objXMLHttp.setRequestHeader "SOAPAction", strSOAPAction ' Some services still require this

' Send the request with the XML payload
objXMLHttp.send strRequestXML

' --- 3. Process the Response ---
If objXMLHttp.Status = 200 Then
    strResponseXML = objXMLHttp.responseText
    Response.Write "<h2>Response XML (Success):</h2>"
    Response.Write "<pre>" & Server.HTMLEncode(strResponseXML) & "</pre>"
Else
    Response.Write "<h2>Error:</h2>"
    Response.Write "<p>Status: " & objXMLHttp.Status & " " & objXMLHttp.statusText & "</p>"
    Response.Write "<p>Response Text: " & Server.HTMLEncode(objXMLHttp.responseText) & "</p>"
End If

' --- Cleanup ---
Set objXMLDoc = Nothing
Set objXMLHttp = Nothing
%>

Error Handling and Response Parsing

Robust error handling is crucial when interacting with external services. The objXMLHttp.Status property will give you the HTTP status code. A 200 OK generally indicates a successful HTTP transaction, but the SOAP response itself might contain application-level errors within the SOAP Fault element.

To parse the response, you can load objXMLHttp.responseText back into an MSXML2.DOMDocument object and then use XPath or selectSingleNode to extract specific data or check for SOAP Faults.

<% 
' ... (previous code to send request and get strResponseXML) ...

If objXMLHttp.Status = 200 Then
    Dim objResponseDoc, objFaultNode
    Set objResponseDoc = Server.CreateObject("MSXML2.DOMDocument.6.0")
    objResponseDoc.async = False
    objResponseDoc.loadXML strResponseXML

    ' Check for SOAP Fault
    objResponseDoc.setProperty "SelectionNamespaces", "xmlns:soap='http://www.w3.org/2003/05/soap-envelope'"
    Set objFaultNode = objResponseDoc.selectSingleNode("//soap:Fault")

    If Not objFaultNode Is Nothing Then
        Response.Write "<h2>SOAP Fault Detected:</h2>"
        Response.Write "<pre>" & Server.HTMLEncode(objFaultNode.xml) & "</pre>"
        ' Extract specific fault details if needed
        ' Dim objCode, objReason
        ' Set objCode = objFaultNode.selectSingleNode("//soap:Code/soap:Value")
        ' Set objReason = objFaultNode.selectSingleNode("//soap:Reason/soap:Text")
        ' If Not objCode Is Nothing Then Response.Write "<p>Fault Code: " & objCode.text & "</p>"
        ' If Not objReason Is Nothing Then Response.Write "<p>Fault Reason: " & objReason.text & "</p>"
    Else
        Response.Write "<h2>SOAP Response (No Fault):</h2>"
        Response.Write "<pre>" & Server.HTMLEncode(strResponseXML) & "</pre>"
        ' Example: Extracting a value from the response
        ' Dim objResultNode
        ' objResponseDoc.setProperty "SelectionNamespaces", "xmlns:soap='http://www.w3.org/2003/05/soap-envelope' xmlns:m='http://your-namespace.com/your-service'"
        ' Set objResultNode = objResponseDoc.selectSingleNode("//m:YourMethodNameResponse/m:YourResultElement")
        ' If Not objResultNode Is Nothing Then
        '     Response.Write "<p>Result: " & objResultNode.text & "</p>"
        ' Else
        '     Response.Write "<p>Could not find expected result element.</p>"
        ' End If
    End If
    Set objResponseDoc = Nothing
Else
    ' HTTP Error already handled above
End If

' ... (cleanup) ...
%>

Example of parsing a SOAP response and checking for faults.