Strange behaviour when the request is malformed

Take the following SOAP 1.2 request:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:typ="http://schemas.servicestack.net/types">
   <soap:Header/>
   <soap:Body>
      <typ:LisServiceDTO>
         <!--Optional:-->
         <typ:Id>1</typ:Id>
      </typ:LisServiceDTO>
   </soap:Body>
</soap:Envelope>

This request works just fine, Id is an integer, it gets deserialized fine.

Now I want to test a malformed request, so instead of 1, I specify a non-valid integer value:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:typ="http://schemas.servicestack.net/types">
   <soap:Header/>
   <soap:Body>
      <typ:LisServiceDTO>
         <!--Optional:-->
         <typ:Id>this is not an integer</typ:Id>
      </typ:LisServiceDTO>
   </soap:Body>
</soap:Envelope>

Testing this request with SOAP UI gives timeout. It seems that the request does not get terminated correctly by ServiceStack. Using SOAP 1.1 yields the same result.

I verified that the ProcessRequestContext gets called.
Also I don’t get any errors in the logger.
I’m using ServiceStack 5.4.1.

EDIT: note that if I call the method using REST, that works, in both cases. It works correctly when I pass Id as integer, and throws me an error when I pass a string. The only case that does not work is the malformed SOAP request.

Please provide the full HTTP Request/Response Headers.

Note the SOAP support only supports requests from the built-in Soap11ServiceClient, Soap12ServiceClient .NET Service Clients and WCF’s Add Service Reference feature.

I’m currently testing the Request, and i’m not using any particular headers.

Here’s the full request detail:

> POST /soap12 HTTP/1.1
> Host: localhost:8080
> User-Agent: insomnia/6.3.2
> Cookie: X-UAId=; ss-id=hJVNzwkq489xRBaGJgbx; ss-opt=temp; ss-pid=OO9SLdt5oEZ2ZH88Ugza
> Content-Type: application/soap+xml
> Accept: application/json
> Accept-Encoding: gzip, deflate
> Content-Length: 291
| <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:typ="http://schemas.servicestack.net/types">
|    <soap:Header/>
|    <soap:Body>
|       <typ:LisServiceDTO>
|          <!--Optional:-->
|          <typ:Id>1</typ:Id>
|       </typ:LisServiceDTO>
|    </soap:Body>
| </soap:Envelope>

There is no response at all when the request is malformed.
Here’s the response details after the correct request:

< HTTP/1.1 200 OK
< Transfer-Encoding: chunked
< Content-Type: application/soap+xml
< Server: Microsoft-HTTPAPI/2.0
< Date: Wed, 20 Mar 2019 16:02:44 GMT
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
  xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Body>
    <LisServiceDTOResponse
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://schemas.servicestack.net/types">
      <Done>true</Done>
    </LisServiceDTOResponse>
  </s:Body>
</s:Envelope>

Malformed SOAP requests should now be treated the same as SOAP Service Exceptions in the latest v5.4.1 that’s now available on MyGet.

The integration test shows how you can deserialize the SOAP Error Response should you need to:

var soap = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<s:Envelope xmlns:s=""http://www.w3.org/2003/05/soap-envelope"" xmlns:a=""http://www.w3.org/2005/08/addressing"">
   <s:Header>
      <a:Action s:mustUnderstand=""1"">AddInts</a:Action>
      <a:MessageID>urn:uuid:e6be43e0-c120-4ba8-920e-7ecaa1823fd2</a:MessageID>
      <a:ReplyTo>
         <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
      </a:ReplyTo>
      <a:To s:mustUnderstand=""1"">http://localhost:50000/api/Soap12</a:To>
   </s:Header>
   <s:Body>
      <AddInts xmlns=""http://schemas.servicestack.net/types"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
         <A>not a</A>
         <B>number</B>
      </AddInts>
   </s:Body>
</s:Envelope>";
var responseXml = ServiceClientBaseUri.CombineWith("/soap12")
    .PostToUrl(soap, requestFilter: req => req.ContentType = "application/soap+xml; charset=utf-8");
    
var doc = new XmlDocument();
doc.LoadXml(responseXml);

var responseMsg = Message.CreateMessage(new XmlNodeReader(doc), int.MaxValue,
    MessageVersion.Soap12WSAddressingAugust2004);

using (var reader = responseMsg.GetReaderAtBodyContents())
{
    var bodyXml = reader.ReadOuterXml();
    var responseType = typeof(AddIntsResponse);
    var response = (AddIntsResponse)DataContractSerializer.Instance
        .DeserializeFromString(bodyXml, responseType);

    response.ResponseStatus.ErrorCode //= SerializationException
    response.ResponseStatus.Message   //= Error trying to deserialize requestType...
}

Using DTOs + Service:

[assembly: ContractNamespace("http://schemas.servicestack.net/types", 
    ClrNamespace = "Your.ServiceModel.Namespace")] // in AssemblyInfo.cs
[DataContract]
public class AddInts : IReturn<AddIntsResponse>
{
    [DataMember]
    public int A { get; set; }
    [DataMember]
    public int B { get; set; }
}

[DataContract]
public class AddIntsResponse
{
    [DataMember]
    public int Result { get; set; }
    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

public class MyServices : Service
{
    public object Any(AddInts request) => new AddIntsResponse {
    	Result = request.A + request.B
    };
}