The Bull Og

Onine since 1994. Offline since 1976.

See also the archive

An individual post follows.

As I was recently serializing objects into XML, I had the need to suppress a few of the elements in the ouput. After looking around, I finally found "XMLElement" and some examples which I reworked in VB .NET. To start with, I have a base class with a method called GenerateXML which each inheriting class overloads. In the method, I use an XmlSerializer to generate the XML and everything was working quite well, until the day before yesterday. The main problem was in a particular subclass that has a property with type DateTime. As all of you know (as do I now,) anytime you try to serialize such an object, you get this in the XML for the property:
<MyDateProperty>0001-01-01T00:00:00.0000000+01:00</MyDateProperty>
When SQL Server tried to update the appropriate table column with the value, I got:
The conversion of a char data type to a datetime data type resulted 
in an out-of-range datetime value.
The statement has been terminated.
I thought the DateTime datatype would be consistently nullable between the .NET framework and SQL Server. Guess I was wrong. The trick became to figure out how to supress the MyDateProperty element in the serialized XML. What to do: So many ways to skin a cat. Then I started thinking "there has to be a way to control serialization of the class in the XMLSerializer." I found the XMLElement attribute along with a really good thread applicable to my case here. There were only two differences in my case: After a good deal of tweaking, I finally got the xxxxSpecified idea (see above) to work inside my subclass. Here's the (VB .NET):
<XmlElement(ElementName:="MyDateProperty", DataType:="date")> _
                                  Property MyDateProperty() As DateTime 
               Get 
                    Return _MyDateProperty 
               End Get 
               Set(ByVal Value As DateTime) 
                     _MyDateProperty = Value 
               End Set 
         End Property  
<XmlIgnore()> Property MyDatePropertySpecified() As Boolean 
               Get 
                     Return _ShowIgnoredElement 
               End Get 
               Set(ByVal Value As Boolean) 
                     _ShowIgnoredElement = Value 
               End Set 
         End Property
All that's left is to set the MyDatePropertySpecified property in a constructor of the subclass. Here's an example:
' Author:  Anthony Jay Bull
' Date:  2006-11-21
' In:  All the params off of the query string as provided 
'       by a NameValueCollection object
' Notes:  The MyDateWebControl is providing the date in this case
'       in the format of "YYYY-DD-MM"

Public Sub New(ByVal formParams As System.Collections.Specialized.NameValueCollection)

           Dim arrPickedDate() As String
           arrPickedDate =_
                      HttpUtility.HtmlEncode(formParams.Item("MyDateWebControl")).Split("-")
           If arrPickedDate.Length = 3 Then
                      Me.MyDateProperty = New DateTime(arrPickedDate(0), _ 
                                             arrPickedDate(2), arrPickedDate(1))
                      Me.MyDatePropertySpecified = True
           Else
                      Me.MyDatePropertySpecified = False
           End If
End Sub
Now, instead of this:
<SomeRootElement>
     <SomeSiblingOfMyDate>Some string value</SomeSiblingOfMyDate>
     <MyDateProperty>0001-01-01T00:00:00.0000000+01:00</MyDateProperty>
</SomeRootElement>
...or even this:
<SomeRootElement>
     <SomeSiblingOfMyDate>Some string value</SomeSiblingOfMyDate>
     <MyDateProperty/>
</SomeRootElement>
I now get this...
<SomeRootElement>
     <SomeSiblingOfMyDate>Some string value</SomeSiblingOfMyDate>
</SomeRootElement>