Skip navigation.

New 2.0 Default: XHTML 1.0 TransitionalAll recent postsNot an AOP Book

Jumping Through Hoops with XML Serialization

On the surface, XML serialization in .NET is easy. Define a class with public fields and properties, optionally decorate with [Xml....] attributes, create an instance of XmlSerializer and you’re done. 99% of all XML serialization samples out there show a simple class with one or two string and int properties. Of course those samples work great! You don’t know what you get yourself into until your class or collection has bool, enum and DateTime properties.

Let’s cook up a contrived example of a user profile class with various properties and just about as useful a driver page. I threw in enum, bool and DateTime properties for this sake of this exercise.

This code produces the following XML rendering of the user profile:

<?xml version="1.0" encoding="utf-16"?>
<User xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <FirstName>John</FirstName>
  <LastName>Doe</LastName>
  <Age>30</Age>
  <Active>true</Active>
  <RegistrationDate>
       2005-09-13T02:13:07.3825728-04:00
  </RegistrationDate>
  <Type>Manager</Type>
</User>

If the standard namespaces bother you, feel free to code your own beautifying XML writer or configure and pass an instance of XmlSerializerNamespaces. For extra points, watch Scott do serialization acrobatics.

Note how the Active, RegistrationDate and Type elements came out. I’ve seen countless complaints in newsgroups about this date format. It causes trouble with web services and XML parsing in SQL Server. I’d be ashamed to show the hack we used to tweak this date format to something SQL Server wouldn’t choke on. Of the gazillion date formats SQL Server doesn’t “get” this one.

Also of note is the enumeration: it’s written as literal text! On the one hand it’s useful—if you add more members to the enumeration, it will still be deserialized fine, but good luck feeding this to, say, SQL Server as it won’t have a clue of what to do with it considering that the underlying column will be of type int or something similar.

Now, here’s my biggest pet peeve of all times: feeding a boolean element (<Active>true</Active> in our case) to OPENXML. I don’t understand why such a derelict language as T-SQL can’t convert “true” and “false” to integer 1 and 0, or bit true and false. Duh! Everybody who hates T-SQL as much as I do say aye. We’ve used SQL Server 2000 XML bolt-ons for two years, and these problems surface once in a while.

Since SQL Server doesn’t play well with XML documents passed to OPENXML, I’d love to control how my class is serialized… except that I can’t! All the control you get is exerted via [Xml…] attributes, but you don’t get to shape the end result of serialization. The fast and the furious of you might’ve noticed the helpful XmlType attribute, but it’s a bummer you can’t apply it to primitive types, i.e. bools, enums, etc (you receive an exception). We’re back to square one.

Monkeying with IXmlSerializable

This sent me looking for ways to write a custom serializer. Several people pointed to an MSDN article by Aaron Skonnard entitled Advanced Type Mappings. In it you’ll find a discussion on how to implement the undocumented and unsupported IXmlSerializable interface. It’s a pretty darn good and simple approach… except for the unsupported part which has “subject to change without notice” all over it. Besides, I codegen my model classes and collections, and found writing a template for an IXmlSerializable implementation quite cumbersome.

Hacking XmlSerializer

Then I stumbled upon a tip by Daniel Cazzulino (who has saved my day more than once). I threw in the chunk of configuration settings he provided, fished for the source code XmlSerializer produced, and cleaned it up a bit. (Oh, boy, did it need cleaning!)

What does this give you? An ability to see what the canned XmlSerializer does and write your own XML writer/reader to exercise control over this process. You can force properties to appear in whichever format you find appropriate for your needs. You also don’t get the horrendous first-hit compilation of the serialization DLL.

Be forewarned: this is not a C# 101 technique. You need to understand what goes on there.

Anyway, after a thorough clean-up I ended up with code I could roll into a template and codegen XML readers and writers!

Conclusion

I guess I can say “problem solved” but at what expense! It took me several days to research every angle of this saga until I settled on this hack. Perhaps, I will revisit it when 2.0 hits the streets.

The BCL team takes pride in how big the Base Class Library has grown. I imagine it would be impossible to make sure every type serializes agreeably to everyone; but, c’mon, give me some control here! Otherwise it’ll remain a half-baked feature, and we’ll have to keep hacking away.

Comments

No comments yet

Emails and Notifications

Would you like to be notified when somebody responds to this post? 

TrackBacks

Sorry, TrackBacks are not allowed.

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):