Friday, September 23, 2005

Messing Around with XML Serialization

In order to work through some of these issues with when to use xml in thin services (previous post), I have been trying to push the use xml serialization (System.Xml.Serialization) on classes which enforce the schema used for messages to the backend service. This xml serialization is also used by the framework for types exposed via web services. If you have XmlSerialization attributes on your own classes, then this automatic serialization will take place in a predictable fashion, and you can also serialize object yourself (say, for sending a stream to a non-soap/non-wsdl service) and expect the same xml. Nothing new in any of this, it has been in the framework all along.

In any case, two minor gotchas I encountered which are both well documented aspects of using the attribution, but were easy for me to miss:
1) Serialized properties read/write, except for arrays/collections. Of course this is true, how else could the object be deserialized - yet when most of my properties were collections, the couple that didn't seem to work were very confusing.
2) Use of the [XmlAnyElement] attribute on types exposed via your webservice can break your wsdl schema due to UPA issues. This UPA concept is explained well by Priya Lakshminarayanan on the Xml team blog. The primary problem is that if you don't differentiate your known types elements from the possible open-ended types, the parser doesn't know what to do with the types it encounters if you can have 0 (minOccurs=0) of the known type. If you use a different namespace to identify unknown (#any) elements, then you can avoid this issue. Or, from the docs:

"You can apply multiple instances of the XmlAnyElementAttribute to a class member, but each instance must have a distinct Name property value. Or, if the same Name property is set for each instance, a distinct Namespace property value must be set for each instance."

For my purposes, names couldn't be identified, so it had to be namespace.
Submit this story to DotNetKicks

No comments: