このエラーは、SOAP サーバーがリクエスト自体は受け取ったものの、XML をサーバー側の型へ変換できなかった時に出やすい典型例です。
System.Web.Services.Protocols.SoapException: Server was unable to read request.
---> System.InvalidOperationException: There is an error in XML document
要するに、通信は届いています。壊れているのは XML の中身です。
まず疑うべき原因
xsd:intに"value"のような文字列を送っている- 必須要素が抜けている
- 子要素の名前空間がずれている
- SOAP 1.1 と 1.2 を取り違えている
- operation の wrapper 要素名が違う
たとえば calculator 系の .asmx サービスでは、次のような JSON 由来の値がそのまま XML になると失敗しやすいです。
{
"intA": "value",
"intB": "value"
}
最短の確認方法
ライブラリの抽象化ではなく、生の request XML を見てください。
curl -v https://example.com/service.asmx \
-H 'Content-Type: text/xml; charset=utf-8' \
-H 'SOAPAction: "http://tempuri.org/Add"' \
--data @request.xml
確認ポイントは次の4つです。
- Envelope の namespace が正しいか
- operation 名が WSDL と一致しているか
- 必須要素が揃っているか
- primitive 値が本当にパース可能か
型不一致の例
NG:
<Add xmlns="http://tempuri.org/">
<intA>value</intA>
<intB>value</intB>
</Add>
OK:
<Add xmlns="http://tempuri.org/">
<intA>2</intA>
<intB>3</intB>
</Add>
xsd:dateTime でも同じで、2026-03-22 は失敗し、2026-03-22T00:00:00 は通ることがあります。
名前空間のズレにも注意
見た目は正しくても、子要素が別 namespace 扱いだと同じエラーになります。
<tns:GetUser xmlns:tns="http://example.com/service">
<userId>42</userId>
</tns:GetUser>
古い ASP.NET SOAP サービスでは、次のように子要素にも同じ namespace が必要なことがあります。
<tns:GetUser xmlns:tns="http://example.com/service">
<tns:userId>42</tns:userId>
</tns:GetUser>
SOAP 1.1 と 1.2 の取り違え
.asmx は SOAP 1.1 前提のことがまだ多いです。
- SOAP 1.1 は
text/xmlとSOAPAction - SOAP 1.2 は
application/soap+xml
ここを間違えると、明示的な VersionMismatch ではなく、この generic な XML document エラーに潰れることがあります。
切り分け手順
- WSDL を取得する
- 必須項目だけの最小 request を作る
- placeholder を全て実値に置き換える
- SoapUI の raw XML と diff を取る
- SOAP version と
SOAPActionを確認する
SOAP を複数のジョブやスクリプトから直接叩いていると、この手の envelope drift が再発しやすくなります。長期的には、XML を1か所で組み立てる形に寄せた方が安定します。