Friday, October 28, 2011

XmlSerializer VS DataContractSerializer

So I am doing a project on the side involving a RESTful WCF Service involving many different types of clients. Recently I was stumped by several issues with the XmlSerializer and the attributes on my data classes: the main issue originated from using WCF to serialize the responses, but not using the DataContractSerializer to deserialize the responses. (Which was clearly a mistake from the start... the lesson here is don't mix and match technologies if you have the tools available native!)

Some fun facts if you find yourself in this predicament (or really, REALLY, want to use XmlSerializer):

  • XmlSerializer will not recognize lists when the complex objects in those lists exist in a different namespace than the list itself, even if you specify this fact on the XmlElement for said list. The same goes for arrays. And give up on loosely types interfaces like 'IEnumerable': the serializer chokes on these.
  • You will be stuck with the yucky 'http://schemas.microsoft.com/2003/10/Serialization/+class namespace' namespace in your xml. This can become VERY inconvenient to your class structure, especially when paired with the first issue.
  • The XmlSerializer will fail if it finds a root node it doesn't understand, but will simply null any inner nodes: make sure to check your entire object, a single element in a complex class can be null without the serializer giving you any warning.
  • Off Topic: One issue I have dealt with a little in other projects, but not for this, is the complete lack of support for serializing multidimensional arrays. One way around it is to turn your array into a single array of complex objects with more in it than just the next 'dimension'. Even a dummy 'int' in the class will work, because it prevents the serializer from trying to 'simplify' the code into a structure it can't handle. (I should note, this recommendation comes from BizTalk experience, not WCF, so it may not apply. But if you are stuck, it's worth trying.)

The simple solution (provided you find this, or some similar article) is to use the serializer intended for WCF, and to stick with the DataContract/DataMember structure of more classic WCF service classes. So long as you specify names and namespaces, and don't care about fine-grained serialization control, everything should work great.

If you look around, you will find lots of recommendations to use 'ResponseFormat = WebMessageFormat.Xml' on your contracts. If you can avoid it, do so - WCF 4 lets clients specify in the request header their return types (an issue I discussed a little in a previous post), and IMO that is a far better way to go, especially if you have any plans of interfacing with clients more at home with JSON (i.e., Android devices).

Happy coding!

References:
http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/
http://social.msdn.microsoft.com/Forums/en-AU/csharpgeneral/thread/dfd587ec-a269-49a9-a1a5-0f69d915c776

No comments:

Post a Comment