SOAP cheat sheet
A scannable SOAP reference: 10 short snippets across 7 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| WSDL contracts and code generation | Generated code turns the contract into classes and a proxy whose methods look like local calls. The WSDL becomes your | lesson |
| Calling a SOAP service, and why REST usually wins | REST wins for new work because it leans on what HTTP already gives you — methods, status codes, caching, proxies — and | lesson |
| SOAP 1.1 versus 1.2 and HTTP bindings | The two versions differ in namespace, content type and how faults travel over HTTP, and a client that guesses wrong | lesson |
| Building a SOAP service: contract-first and code-first | The direction you choose is really a decision about where the review of the interface happens. Contract-first puts it | lesson |
| Attachments and binary data: MTOM and SwA | Base64 inside the envelope is simple and wasteful. MTOM keeps the XML readable and sends the bytes as raw binary | lesson |
| Interoperability between .NET, Java and legacy stacks | Most cross-vendor failures come from a handful of known divergences in encoding, dates, nulls and empty collections | lesson |
| SOAP in the enterprise: ESBs, gateways and middleware | In large organisations SOAP rarely reaches the service directly. Knowing what the gateway does explains most | lesson |
Quick snippets
WSDL contracts and code generation
Generating a client
# Java: JDK ships wsimport; Jakarta's wsdl2java is the maintained option
wsimport -keep -p com.example.quotes -d out https://api.example.com/quotes?wsdl
wsdl2java -d out -p com.example.quotes https://api.example.com/quotes?wsdl
# .NET
dotnet svcutil https://api.example.com/quotes?wsdl
# Python: ask for a plain dictionary instead of a proxy class
python -m zeep https://api.example.com/quotes?wsdlFull lesson: WSDL contracts and code generation →
Calling a SOAP service, and why REST usually wins
The call on the wire
curl -sS https://api.example.com/quotes \
-H 'Content-Type: text/xml; charset=utf-8' \
-H 'SOAPAction: "urn:example:quotes/GetQuote"' \
--data-binary @request.xmlFull lesson: Calling a SOAP service, and why REST usually wins →
SOAP 1.1 versus 1.2 and HTTP bindings
What actually differs
POST /OrderService HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:example:orders/PlaceOrder"
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<PlaceOrder xmlns="urn:example:orders"><sku>A-1</sku><qty>2</qty></PlaceOrder>
</soap:Body>
</soap:Envelope>
What actually differs
POST /OrderService HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action="urn:example:orders/PlaceOrder"
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<PlaceOrder xmlns="urn:example:orders"><sku>A-1</sku><qty>2</qty></PlaceOrder>
</env:Body>
</env:Envelope>Full lesson: SOAP 1.1 versus 1.2 and HTTP bindings →
Building a SOAP service: contract-first and code-first
The mechanics of each direction
# Contract-first with JAX-WS: generate the portable artifacts, then implement
wsimport -keep -p com.example.orders -d build/classes contract.wsdl
# .NET: generate a client or a server-side abstract class
dotnet tool install --global dotnet-svcutil
dotnet-svcutil contract.wsdl --outputDir Generated
# Java: publish a contract-first endpoint without a container
# (endpoint is the portable JAX-WS API)
# Endpoint.publish("http://0.0.0.0:8080/orders", new OrderServiceImpl());
# then check it
curl -s "http://localhost:8080/orders?wsdl" | head -20Full lesson: Building a SOAP service: contract-first and code-first →
Attachments and binary data: MTOM and SwA
Three ways to send bytes
Content-Type: multipart/related; type="application/xop+xml";
start="<[email protected]>"; start-info="application/soap+xml";
boundary="MIME_boundary"
Practical rules
// Enable MTOM on a WCF-style binding and stream the body
var binding = new BasicHttpBinding
{
MessageEncoding = WSMessageEncoding.Mtom,
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = 64L * 1024 * 1024,
ReaderQuotas = { MaxArrayLength = 64 * 1024 * 1024 }
};
// TransferMode.Streamed matters more than the size limits:
// it keeps the payload off the managed heap.Full lesson: Attachments and binary data: MTOM and SwA →
Interoperability between .NET, Java and legacy stacks
The known divergences
# Normalise both responses and diff them
xsltproc tools/compare.xsl java-response.xml > java.txt
xsltproc tools/compare.xsl dotnet-response.xml > dotnet.txt
diff -u java.txt dotnet.txtFull lesson: Interoperability between .NET, Java and legacy stacks →
SOAP in the enterprise: ESBs, gateways and middleware
What the middleware does
<!-- A gateway-added header you should expect and tolerate -->
<soap:Header>
<gw:RoutingId xmlns:gw="urn:example:gateway">abc-123</gw:RoutingId>
<gw:ReceivedAt xmlns:gw="urn:example:gateway">2026-09-18T10:00:03Z</gw:ReceivedAt>
<wsse:Security><!-- the gateway may replace the original token --></wsse:Security>
</soap:Header>
What the middleware does
# Prove where a failure happens: measure the gap between hops
curl -s -o /dev/null -w 'gateway connect=%{time_connect} total=%{time_total}\n' \
-X POST https://gateway.example.com/orders --data-binary @req.xml
curl -s -o /dev/null -w 'direct connect=%{time_connect} total=%{time_total}\n' \
-X POST https://orders.internal/OrderService --data-binary @req.xmlFull lesson: SOAP in the enterprise: ESBs, gateways and middleware →
FAQ
Is this SOAP cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
XML XPath XSLT RESTful APIs RSS & Atom
Last refreshed 2026-09-27.