2
votes

I have a super-simple ServiceStack webservice configured using the latest Nuget package (3.8.3 I believe?). The main change I made was to call ResultContext.ToOptimizedResult(object) to compress the response message if the calling client supports it. The Service is defined as follows:

public class PingService : BaseService<Ping>
    {
        protected override string OperationName { get { return "Ping"; } }

        protected override object Run(Ping request)
        {
            // Implementation removed for brevity
            return new PingResponse();
        }

        protected override object OnAfterExecute(object response)
        {
            //return response;
            return RequestContext.ToOptimizedResult(response);
        }
    }

The Client code is as follows:

var jsonClient = new JsonServiceClient("http://localhost/WebAppServiceV3/api");
var response = jsonClient.Send<PingResponse>(new Ping { LoginInfo = new ClientLoginInfo { UserName = "guest", Password = "guest", ClientPlatform = "TEST", ClientVersion = "1.3", InstanceUID = Guid.NewGuid().ToString() } });
Console.WriteLine(response.ToJson() + "\n");

var jsvClient = new JsvServiceClient("http://localhost/WebAppServiceV3/api");
response = jsvClient.Send<PingResponse>(new Ping { LoginInfo = new ClientLoginInfo { UserName = "guest", Password = "guest", ClientPlatform = "TEST", ClientVersion = "1.3", InstanceUID = Guid.NewGuid().ToString() } });
Console.WriteLine(response.ToJsv() + "\n");

var xmlClient = new XmlServiceClient("http://localhost/WebAppServiceV3/api");
response = xmlClient.Send<PingResponse>(new Ping { LoginInfo = new ClientLoginInfo { UserName = "guest", Password = "guest", ClientPlatform = "TEST", ClientVersion = "1.3", InstanceUID = Guid.NewGuid().ToString() } });
Console.WriteLine(response.ToXml() + "\n");

var soap11 = new Soap11ServiceClient("http://localhost/WebAppServiceV3/api");
response = soap11.Send<PingResponse>(new Ping { LoginInfo = new ClientLoginInfo { UserName = "guest", Password = "guest", ClientPlatform = "TEST", ClientVersion = "1.3", InstanceUID = Guid.NewGuid().ToString() } });
Console.WriteLine(response.ToXml() + "\n");

var soap12 = new Soap12ServiceClient("http://localhost/WebAppServiceV3/api");
response = soap12.Send<PingResponse>(new Ping { LoginInfo = new ClientLoginInfo { UserName = "guest", Password = "guest", ClientPlatform = "TEST", ClientVersion = "1.3", InstanceUID = Guid.NewGuid().ToString() } });
Console.WriteLine(response.ToXml() + "\n");

The Json, Jsv, and Xml clients all receive compressed responses here and work fine. The Soap clients throw exceptions when the line return ResultContext.ToOptimizedResult(result) is included in the service instead of just return result.

It seems that the client is expecting a <PingResponse/> element but receives a <Base64Binary/> element instead when a compressed result is returned:

Error in line 1 position 185. Expecting element 'PingResponse' from namespace 'http://schemas.datacontract.org/2004/07/IMDSSWebService_SS.ServiceModel'.. Encountered 'Element'  with name 'base64Binary', namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.

Compression On (Fails)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <base64Binary xmlns="http://schemas.microsoft.com/2003/10/Serialization/">...</base64Binary>
  </s:Body>
</s:Envelope>

Compression Off (Succeeds)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <PingResponse>...<PingResponse>
  </s:Body>
</s:Envelope>

Any insight on what I may be doing wrong here? Thanks in advance.

2

2 Answers

1
votes

Compression for SOAP is not currently supported.

You can file an issue at https://github.com/ServiceStack/ServiceStack/issues to request and track this feature.

0
votes

We've run into this before, except with the JSON serializer in ServiceStack... You have to explicitly specify the return type:

protected PingResponse Run(Ping request)
{
    // Implementation removed for brevity
    return new PingResponse();
}

(e.g. you can not use object as the return type.)

We went back and forth trying all different methods (dyanmic, generics, etc.) and SerivceStack just doesn't globally support these because of its data contract nature.

What we ended up having to do is create API methods for each type where were were going to use generics/simple objects (e.g. RunPingResponse(), RunOtherResponse(), etc). :(