SOAP

Comparing SOAP to REST APIs and working with SOAP services in .NET applications

Introduction to SOAP

SOAP (Simple Object Access Protocol) is a standardized, XML-based messaging protocol for exchanging structured information in web services. Developed in 1998 and later maintained by the World Wide Web Consortium (W3C), SOAP was designed to enable communication between applications running on different operating systems, with different technologies and programming languages.

Unlike REST, which is an architectural style, SOAP is a protocol with specific standards and rules. It typically works with HTTP, but can also operate over other protocols such as SMTP, TCP, or JMS.

Key Features of SOAP

  • XML-Based: All SOAP messages use XML format
  • Protocol Independence: Can work over different transport protocols (HTTP, SMTP, TCP)
  • Strongly Typed: Enforces strict contracts through WSDL
  • Built-in Error Handling: Through SOAP faults
  • Security: WS-Security provides enterprise-level security features
  • Reliability: WS-ReliableMessaging ensures message delivery
  • Transaction Support: Through WS-AtomicTransaction and WS-Coordination
  • Stateless by Default: But supports stateful operations if needed
  • Extensibility: Through SOAP extensions and WS-* specifications

SOAP vs REST

Here’s how SOAP compares to REST:

FeatureSOAPREST
FormatXML onlyAny format (JSON, XML, HTML, etc.)
ProtocolMultiple protocolsHTTP primarily
Service DefinitionWSDL (required)OpenAPI/Swagger (optional)
BandwidthHigher (XML verbose)Lower (typically JSON)
CacheNot cacheableCacheable
SecurityWS-Security, enterprise featuresHTTPS, JWT, OAuth
Transaction SupportBuilt-inMust implement custom
Failure RecoveryRetry logic, error infoTypically none
PerformanceSlower due to XML parsingFaster, lighter weight
Learning CurveSteeperSimpler

When to Use SOAP

SOAP is particularly well-suited for:

  1. Enterprise Integration: When connecting complex enterprise systems
  2. Formal Contracts: When you need a strict, enforceable contract
  3. Stateful Operations: When maintaining state across operations is required
  4. Reliable Messaging: When guaranteed delivery is essential
  5. Complex Transactions: When you need ACID transaction support
  6. Advanced Security: When WS-Security features are needed
  7. Independent Transport: When you need to use non-HTTP transport layers

SOAP Message Structure

A SOAP message is an XML document with a specific structure:

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header>
    <!-- Optional header information -->
    <auth:Credentials xmlns:auth="http://example.org/auth">
      <auth:Username>username</auth:Username>
      <auth:Password>password</auth:Password>
    </auth:Credentials>
  </soap:Header>
  <soap:Body>
    <!-- The main payload of the message -->
    <m:GetStockPrice xmlns:m="http://example.org/stock">
      <m:StockName>MSFT</m:StockName>
    </m:GetStockPrice>
  </soap:Body>
</soap:Envelope>

SOAP Envelope

The root element of every SOAP message. It contains:

  • Header: Optional element with metadata (authentication, transaction info)
  • Body: Required element containing the actual request or response data

SOAP Fault

When an error occurs, SOAP returns a standardized fault message:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <soap:Fault>
      <soap:Code>
        <soap:Value>soap:Sender</soap:Value>
      </soap:Code>
      <soap:Reason>
        <soap:Text xml:lang="en">Invalid stock symbol</soap:Text>
      </soap:Reason>
      <soap:Detail>
        <ex:ValidationError xmlns:ex="http://example.org/faults">
          <ex:Message>Stock symbol 'XYZ' is not valid</ex:Message>
        </ex:ValidationError>
      </soap:Detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

WSDL: Web Service Description Language

SOAP services are described using WSDL, an XML-based interface description language. WSDL defines:

  • Service endpoints
  • Available operations
  • Message formats
  • Data types
  • Binding information

A simplified WSDL example:

<?xml version="1.0"?>
<definitions name="StockQuote"
    targetNamespace="http://example.org/stockquote"
    xmlns:tns="http://example.org/stockquote"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns="http://schemas.xmlsoap.org/wsdl/">

  <!-- Data type definitions -->
  <types>
    <xsd:schema targetNamespace="http://example.org/stockquote">
      <xsd:element name="GetStockPrice">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="StockName" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="StockPriceResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="Price" type="xsd:decimal"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </types>

  <!-- Message definitions -->
  <message name="GetStockPriceInput">
    <part name="parameters" element="tns:GetStockPrice"/>
  </message>
  <message name="GetStockPriceOutput">
    <part name="parameters" element="tns:StockPriceResponse"/>
  </message>

  <!-- Port type (interface) -->
  <portType name="StockQuotePortType">
    <operation name="GetStockPrice">
      <input message="tns:GetStockPriceInput"/>
      <output message="tns:GetStockPriceOutput"/>
    </operation>
  </portType>

  <!-- Binding (protocol details) -->
  <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetStockPrice">
      <soap:operation soapAction="http://example.org/GetStockPrice"/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

  <!-- Service definition -->
  <service name="StockQuoteService">
    <port name="StockQuotePort" binding="tns:StockQuoteSoapBinding">
      <soap:address location="http://example.org/stockquote"/>
    </port>
  </service>
</definitions>