I have been using XML serialization in .Net 1.1 for quite some time and never ran into any problems before until quite recently. A couple of days ago, while I was working at a client site, I used xsd to generate an C# class for an XML file as usual. But when I ran it, I would receive some runtime exceptions like the following screen shot:
And each time I ran the program the exception would show a different DLL missing. At first, I was trying to find the missing DLL but of course could not find it. After a few tries, I realized that this must be something wrong with the xsd generated class. And sure enough, after searching the internet for the exception message An unhandled exception of type ‘System.IO.FileNotFoundException’ occurred in mscorlib.dll, quite a few people had ran into the exact same problem. After some research on the internet, it seems that the solution is quite simple. Basically, it has something to do with the jagged array in the generated class. And the fix, most of the time, is to remove the unnecessary dimension off the affected class manually. To reproduce this error in .Net 1.1, consider the following XML file (Orders.xml):
<?xml version="1.0" encoding="utf-8"?> <Order> <customer> <firstName>Kerry</firstName> <lastName>Wong</lastName> <orders> <item>123456789</item> <item>123456780</item> <item>123456788</item> </orders> </customer> <customer> <firstName>Jessica</firstName> <lastName>Wong</lastName> <customerStatus>none</customerStatus> <orders> <item>123456780</item> <item>123456788</item> </orders> </customer> </Order>
First you need to generate the xsd schema by using
xsd Orders.xml
then, generate the class using
xsd Orders.xsd /c /l:cs /namespace:XMLSerializationTest
To test the generated class, write a class including the following code:
fs = new FileStream("Orders.xml", FileMode.Open); XmlReader reader = new XmlTextReader(fs); Order orders = (Order) x.Deserialize(reader); fs.Close();
when you run the code you would receive the error similar to the one shown above. When examining the generated Orders.cs class, you would see code in OrderCustomer class like this:
[System.Xml.Serialization.XmlArrayAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute(
"item", typeof(OrderCustomerOrdersItem),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public OrderCustomerOrdersItem[][] orders;
and when you remove one dimension from the generated orders array, the problem would disappear. It is quite obvious that the orders is just a one dimensional array in the example I gave above. It seems that this is absolutely a .Net 1.1 framework bug, because when you use xsd to generate the same class in .Net framework 2.0 beta 2, the example I gave would work correctly. And if you take a look at the generated class, the corresponding lines would look like:
[System.Xml.Serialization.XmlElementAttribute( "orders", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] public OrderCustomerOrders[] orders { get { return this.ordersField; } set { this.ordersField = value; } }
Which is slightly different then the version generated by 1.1 framework, but clearly the orders is a one dimensional array. I have to say that this bug is quite stunting because you do not know when it would kick in when you are coding and for classes not as simple as the example I gave, it would take quite some effort to correctly identify the affected lines. Luckily, Chris Sells created a great tool XmlSerializerPreCompiler to test your generated assembly to see whether or not it can be serialized correctly in framework 1.1. Anyway, I am glad that Microsoft fixed this bug in the coming version of the .Net framework.