Here’s one for you. I have two Windows Server 2003 environments, and in one environment, a .NET object correctly serializes to XML, and in the next environment it does not.
Let’s set this up. First, I have an existing schema like below where my datetime/number types are both nillable, and have a minOccurs of 0. So, they could exist and be null, or not exist entirely.
Next, I generate a typed object for this schema using xsd.exe. The generated class contains my schema nodes, of course, but xsd.exe also inserts these boolean “[fieldname] + Specified” variables. Now these field accessors have the XmlIgnoreAttribute, so they don’t get included in the XML document, but rather can be used to check if a field exists. If the value is false, the the XML serializer doesn’t include the corresponding field in the output.
So far so good. I’ve built a really simple application that takes an XML string and loads it into my .NET object via the XmlSerializer Framework object. On my development machine, executing this step results in a MessageBox window that shows the object properties after the Xml deserialization occurred.
As you can see, all the values in my original XML document converted fine, and, the “specified” fields are both set to true because the corresponding fields have values. If I take this little application, and run it on our common development environment, I get the exact same result (I’ve also tested this on some co-worker’s machines). However, if I run this application in our TEST environment (same OS, same .NET framework version as previously tested environments), I get the following result:
What, what, what?? I still have values present for the integer (“Age”) and datetime (“BirthDate”) but the “specified” fields are now false. What’s the ramification? Turning this object back into XML in this TEST environment results in this …
Yowza. Now those fields don’t get serialized back into the XML document. Not good. As for solutions, the quickest one is to remove the auto-generated “specified” fields from the .NET object which results in everything serializing and deserializing just fine. However, I don’t like mucking with auto-generated code because you have to remember what changes you’ve made for all future releases.
Thoughts as to what could cause this? A .NET hotfix, something environmental? I’ve included my little test application here, so feel free to download and execute the quick test on your machine and post the results in the comments.
Technorati Tags: XML
Richard …
First, congrats on joining the ranks of BizTalk MVPs. Love your blog, and glad to see you recognized.
Second, you’ve run into an edge case but the good news is that there is a hotfix available, bad news is you have to go ask for it. Here is the relevant link :
http://support.microsoft.com/kb/925272
Tim,
You are a man among boys. I can’t believe this hotfix didn’t turn up in any of my search results.
Tim, thank you so much!
So does this mean that Richard had different versions of .NET 2.0 (or at least System.xml.dll) on his dev and test environments?
Hey thiagoblog,
I hope it means that my development environment has more up-to-date patches, or, had an application installed there which brought the update along with it.
The assembly version between environments was identical.
Hmm, that is very tricky, isn’t it? The patch updates System.Xml.dll to fix the issue and you were running the same version between the environments.
The issue was probably fixed in some other dll with the updates you had in the dev environments, while the patch fixes it directly in System.Xml.dll.
Just realized I can choose my actual name instead of my login to show in the comments I leave…
The question is which of those two results is correct. Xsd.exe generates the de bSpecified boolean if you specify the element as being optional (minOccurs=0).
If minOccurs is not added, the bSpecified boolean is not generated.
In this case the age attribute of the object is filled, so the serializer has to set the value of the bSpecified boolean to true, so the question is why doesn’t de serializer automatically set the boolean to true?