Strange bug with DataContractSerializer during Deserialization
-
Wednesday, July 30, 2008 11:52 PMHi,
I am trying to deserialize an XML into an object using DataContractSerializer .
Here is my issue:
My XML is like:
<Cobranding_CSS_TC>
<EnableCustomCSSSettings>1</EnableCustomCSSSettings>
<LeftFrameBackgroundColor>#ffx</LeftFrameBackgroundColor>
<RightFrameBackgroundColor>#ffy</RightFrameBackgroundColor>
<FooterFrameBackgroundColor>#ffz</FooterFrameBackgroundColor>
</Cobranding_CSS_TC>
My Class definition is:
[DataContract(Name = "Cobranding_CSS_TC")]
public class CSSData
{
[DataMember]
public string EnableCustomCSSSettings { get; set; }
[DataMember]
public string LeftFrameBackgroundColor { get; set; }
[DataMember]
public string RightFrameBackgroundColor { get; set; }
[DataMember]
public string FooterFrameBackgroundColor { get; set; }
}
When I get the deserialized object back, it fills all properties correctly except 'FooterFrameBackgroundColor', which is set to NULL. However, is value was expected as '#ffz'.
Strangely, if I change the order of elements in my XML such that FooterFrameBackgroundColor appears after EnableCustomCSSSettings but before LeftFrameBackgroundColor, it starts working!
Seems that the XML is being read in forward-only mode, and deserialization happens alphabetically, which is causing this issue.
Please help, as this seems to be very flaky.
Answers
-
Thursday, July 31, 2008 3:30 AM
The order of the elements is important in the deserialization. As you mentioned, the default order is alphabetical, not the order in which the elements are declared, but you can change it by using the Order property in the [DataMember] attribute:
[DataContract(Name = "Cobranding_CSS_TC")]
public class CSSData
{
[DataMember(Order = 1)]
public string EnableCustomCSSSettings { get; set; }
[DataMember(Order = 2)]
public string LeftFrameBackgroundColor { get; set; }
[DataMember(Order = 3)]
public string RightFrameBackgroundColor { get; set; }
[DataMember(Order = 4)]
public string FooterFrameBackgroundColor { get; set; }
}
All Replies
-
Thursday, July 31, 2008 3:30 AM
The order of the elements is important in the deserialization. As you mentioned, the default order is alphabetical, not the order in which the elements are declared, but you can change it by using the Order property in the [DataMember] attribute:
[DataContract(Name = "Cobranding_CSS_TC")]
public class CSSData
{
[DataMember(Order = 1)]
public string EnableCustomCSSSettings { get; set; }
[DataMember(Order = 2)]
public string LeftFrameBackgroundColor { get; set; }
[DataMember(Order = 3)]
public string RightFrameBackgroundColor { get; set; }
[DataMember(Order = 4)]
public string FooterFrameBackgroundColor { get; set; }
} -
Thursday, July 31, 2008 6:57 PMThanks a bunch for prompt reply.
After some investigation I figured it out :-)
We do not have control over the given XML as it comes from external component. And the order of elements in that XML is not alphabetical.
As a work around, we grouped the elements in different groups and it has started working. Thx.
However, I was wondering if it may result in a maintanence nightmare as every time they would add new elements in XML, we would have to 'carefully' group the properties in different orders.
Is there a better solution for this? -
Thursday, July 31, 2008 8:33 PMThe schema representation for members of data contracts is <xs
equence>, so the order is indeed important. The DataContractSerializer (the default serializer in WCF) does not support arbitrary schema constructs, but the XmlSerializer supports most of them (including the xs:all, which seems like the construct you're interested in), so that can be an option you can consider.

