Batch request fails when using the XmlServiceClient

Hello,

I’m trying to use the SendAll method of the XmlServiceClient to batch some requests but I’m getting an exception as shown below. If I debug the service, I can see that the Any(HelloBatch request) method is called 3 times but the responses are not returned. I tried the same code with the JsonServiceClient and it works as expected. Do I have to do something for the batch requests to work with the XmlServiceClient?

Here’s the code I used to reproduce the issue. This code uses version 4.0.47 from 2015-09-30 and I have the same result with version 4.0.42.

Request:

    [Route("/helloBatch/{Name}", Verbs = "GET")]
    public class HelloBatch : IReturn<HelloBatchResponse>, IGet
    {
        public string Name { get; set; }
    }
Response:

    public class HelloBatchResponse
    {
        public string Greeting { get; set; }
    }
Service:
  public HelloBatchResponse Any(HelloBatch request)
  {
      return new HelloBatchResponse
             {
                 Greeting = "Hello " + request.Name
             };
  }
Unit test used to reprocude the issue:
  ServiceClientBase client = new XmlServiceClient("..."); // it works if I use JsonServiceClient
  client.SendAll(new[]
                 {
                     new HelloBatch{Name = "A"},
                     new HelloBatch{Name = "B"},
                     new HelloBatch{Name = "C"}
                 });
Request headers:
POST http://.../xml/reply/HelloBatch[] HTTP/1.1
Accept: application/xml
User-Agent: ServiceStack .NET Client 4.047
Accept-Encoding: gzip,deflate
Content-Type: application/xml
Host: ...
Content-Length: 288
Expect: 100-continue
Connection: Keep-Alive

<ArrayOfHelloBatch xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ServiceStackWeb.ServiceModel"><HelloBatch><Name>A</Name></HelloBatch><HelloBatch><Name>B</Name></HelloBatch><HelloBatch><Name>C</Name></HelloBatch></ArrayOfHelloBatch>
Response:
HTTP/1.1 400 Bad Request
Cache-Control: private
Content-Type: application/xml
Vary: Accept
Server: Microsoft-IIS/8.0
X-AutoBatch-Completed: 3
X-Powered-By: Overture/1.0.0.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRG93bmxvYWRzXFZpc3VhbCBTdHVkaW8gMjAxMlxQcm9qZWN0c1xTZXJ2aWNlU3RhY2tXZWJcU2VydmljZVN0YWNrV2ViXFNlcnZpY2VTdGFja1dlYlx4bWxccmVwbHlcSGVsbG9CYXRjaFtd?=
X-Powered-By: ASP.NET
Date: Mon, 19 Oct 2015 14:55:06 GMT
Content-Length: 3690

<?xml version="1.0" encoding="utf-8"?><ArrayOfanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><anyType xmlns:d2p1="http://schemas.datacontract.org/2004/07/ServiceStackWeb.ServiceModel" i:type="d2p1:HelloBatchResponse" /></ArrayOfanyType><?xml version="1.0" encoding="utf-8"?><ErrorResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.servicestack.net/types"><ResponseStatus><ErrorCode>SerializationException</ErrorCode><Message>Type 'ServiceStackWeb.ServiceModel.HelloBatchResponse' with data contract name 'HelloBatchResponse:http://schemas.datacontract.org/2004/07/ServiceStackWeb.ServiceModel' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.</Message><StackTrace>   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
   at WriteArrayOfanyTypeToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
   at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph)
   at ServiceStack.Text.XmlSerializer.SerializeToStream(Object obj, Stream stream)
   at ServiceStack.Host.ContentTypes.&lt;GetStreamSerializer&gt;b__5(IRequest r, Object o, Stream s)
   at ServiceStack.Host.ContentTypes.&lt;&gt;c__DisplayClass3.&lt;GetResponseSerializer&gt;b__2(IRequest httpReq, Object dto, IResponse httpRes)
   at ServiceStack.HttpResponseExtensionsInternal.WriteToResponse(IResponse response, Object result, ResponseSerializerDelegate defaultAction, IRequest request, Byte[] bodyPrefix, Byte[] bodySuffix)</StackTrace><Errors i:nil="true" /><Meta xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true" /></ResponseStatus></ErrorResponse>

This should now be fixed with this commit. This change is available from v4.0.47+ that’s now on MyGet.

Although I’m not sure why you’d use the more stricter, fragile and verbose XmlServiceClient? Since the XML Format is an impl detail behind a generic Service Client what benefit is there to using XML over JSON?

I agree that JSON is superior to XML in that context; I’m just trying to support both JSON and XML clients in my application since this is ‘free’ in ServiceStack.

1 Like