Asked by:

Custom Serialization with WCF services

Question

1) How do I override the default serialization for a WCF Service?ie: Given the following: ServiceResponse SomeMethodCall(ServiceRequest) - how do I override the serialization of ServiceResponse to be custom (for example if I just wanted to serialize ServiceResponse to a comma delimited string over the wire)

2) How can I override the deserialization of the proxy-generated ServiceResponse on the client-side? (Silverlight client)

I've run quite a bit of reading, but am getting lost in the sea of DataContractSerializers / IXMLSerialize etc etc.

3) Is it possible to provide a serialization switch in the method call, and then use the framework serialization, or the custom serialization depending on the switch.

Reasoning:With our in-house client, we would like to minimise comms across the wire with custom serialization, but to 3rd party consumers of the service, they can consume to service as per usual.

All replies

1) This blog post talks about creating and implementing custom serializers. So you could create your own serilalizer to serialize to a comman delmited file.http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

2) On the client side, it is not going to understand your format unless you manually tell it the format to decode.

3) Since serialization is declared on the contract, you cant really just have a switch in teh method call. You will have to have seperate endpoints each with a different contract to the same service. You may want to look at this too: http://www.danrigsby.com/blog/index.php/2008/04/10/specifying-a-different-serializer-per-endpoint-in-wcf/

Now I get what I have to do (implement a custom serializer, and declare different endpoints which use the custom serializer and the dataContractSerialzer seperately)

As to the how: Would the ServiceResponse object declare both the [DataContract] tag (which implemented the DataContractSerializer), and IXMLSerializable interface, and then depending on which endpoint is being used, the specific serializer is implemented?For custom serialization (which is not XML), I take it I need to implement IXMLSerializable and override the ReadXml and WriteXml for that kind of serialization control - or is there a different methodolgy.

PS:Thanks for the info on your blog - quite a few interesting articles.

It's not immediately clear from your blog post as to how to go about creating a custom serializer - seems it just differentiates using DataContractSerializer vs std xml serialization (ala aspx web services). How would I go about implementing a custom serializer that serializes to a delimited string?...and how does this effect the request and response objects being sent over the wire considering that they need to be valid for both endpoints that are defined. - It seems that you cannot define [DataContract] attribute, as well as implement IXmlSerializable on the same object.

PS: if the request and response objects implemented only IXMLSerializable, then theoretically one could pass in a serialization switch in the method, and then check the value of the switch on the ReadXML and WriteXml method overrides of the IXmlSerializable implementation.The only reason that I'm not following this path is that I don't want to expose the entire object hierarchy to the consumer who just wants delimited "compact" serialization - hence the definition of 2 different end-points makes more sense.

As mentioned, the only part I'm missing is how to implement my own custom serializer that will be used by the [XmlSerializerFormat] service endpoint.

David - thanks for the post, but it doesn't help much.What I need (for the custom endpoint that doesn't implement DataContractSerializer), is serialization that doesn't use the xml format at all (verbose tags etc.) - the ServiceResponse object returned needs to serialize into a delimited string, with no xml tags to speak of.

2) 2 endpoints: 1 implementing DataContractSerializer, and another implementing custom serialization (string delimitation of the object) ie: ServiceResponse will be exposed via DataContractSerializer with all it's fields, but with only a single string field for the CustomSerialization implementation. The service consumer should be able to subscribe to a wsdl definition per endpoint, thus only generating proxy classes for the endpoint which they are using.

Dan's link on specifying 2 endpoints on the same service shows how to do this

His post is quite helpful, but falls short of explaining how to consume the seperate endpoints - at the moment I point the client project to the svc file location (which points to a service, not an endpoint - so maybe something can be done here?), which generates proxy classes for both endpoint implementations - I need a way of addressing only a single endpoint.

For now (until I gain more how-to knowledge), it seems like I'll be dumping the dual endpoints, and just be implementing IXMLSerializable on all the "DataContract" objects (you can't implement [DataContract] and implement IXmlSerializable)Then every service method will have a serializeFormat parameter, which the IXmlSerializable implementations (ReadXml(), WriteXml() ) will analyse, and either produce a comma delimited string, or well formed xml. The only down-side of this implementation, is that the proxy classes generated will contain the full object definitions for the "DataContract" objects, which is unecessary bloat for a consumer just wishing to implement the custom delimited serialization (that - and to have to specify a SerializeFormat parameter for every method call )

The purpose of all this is the following:3rd party consumers should be able to generate full "DataContract" objects from the wsdl, and use the service as per usual.For in-house service client (silverlight web application), we should have the ablilty to ignore the object structures (and not expose them) and use prepriotoy serialization logic (which is implemented server and client-side) This facilitates ultra-slim data transfer across the wire, and cuts down on the size of generated proxy classes (which is also initially transferred over the wire to the client) - the aim being to improve performance as much as possible across the wire (esp considering 3rd world web infrastructure)

Thanks for the post - it's an interesting article.The implementation decribed would be 100% for my custom implementation - but then would require that I expose a completely different service to 3rd parties in order for them to get proper return objects. (and generate them from the wsdl exposed from the service)

What I'm after is "simply" the same service implementation, but different endpoints (which as discussed previously can be achieved by implementing inherited interfaces), each endpoint having it's own wsdl address which expose it's specific format.eg: for the DataContractSerializer endpoint, ServiceResponse object would be exposed on it's wsdl as<ServiceResponse>

<attribute1/><attribute2/><attribute3/>

</ServiceResponse>...and be exposed in the XMLFormatSerializer endpoint wsdl as<ServiceResponse>

For wcf , all you ideally need is a custom message encoder the custom message encoder is all that is required to convert Message to byte array and viceversa. Inorder to use a custom format you will also need a custom impl of the Message unless you want
ur custom encoder to tranform to/from your custom format to a supported format such as XML. However, the biggest problem you will have is with encoding soap headers, ur custom format has to support that too. And yes many ppl know how to do it, atleast I can't
give out the source due to closed source/nda.