views:

1165

answers:

2

I want to serialize DateTime so that when DateTime is null I dont get the tag itself.

I have also set bool specified for the above but my problem is DateTime being of value type it will never be null hence the bool specified will always be true for it.

I even tried replacing DateTime to System.Nullable but I get Serialization Error when Sending request or receiving response from WebService.

Is there any way out ?

A: 

You will probably need to implement IXmlSerializable and manually serialize your type, you will then be able to use the Nullable<DateTime>. Here's an example:

public class MyData : IXmlSerializable
{
    public Nullable<DateTime> MyDateTime { get; set; }

    public void WriteXml(XmlWriter writer)
    {
        if (this.MyDateTime.HasValue)
        {
            writer.WriteStartElement("MyDateTime");
            writer.WriteValue((DateTime)this.MyDateTime);
            writer.WriteEndElement();
        }
    }

    public void ReadXml(XmlReader reader)
    {
        if (reader.ReadToDescendant("MyDateTime"))
        {
            this.MyDateTime = reader.ReadElementContentAsDateTime();
        }
    }

    public XmlSchema GetSchema()
    {
        return null;
    }
}

Using this:

MyData md = new MyData { MyDateTime = null };
XmlSerializer ser = new XmlSerializer(typeof(MyData));
using (var writer = XmlWriter.Create(@"d:\temp\test.xml"))
{
    ser.Serialize(writer, md);
}

using (var reader = XmlReader.Create(@"d:\temp\test.xml"))
{
    md = (MyData)ser.Deserialize(reader);
    WL(md.MyDateTime.HasValue);
}

Change that first line to MyDateTime = DateTime.Now to see the alternate behaviour. This writes and reads the MyDateTime value depending on whether it's present in the XML:

<?xml version="1.0" encoding="utf-8"?>
<MyData />

<?xml version="1.0" encoding="utf-8"?>
<MyData>
    <MyDateTime>2009-08-06T10:10:14.8311049+01:00</MyDateTime>
</MyData>
Simon Steele
Can you elaborate it more
Added an example, seems to work for me! I think this should work for your web service result too.
Simon Steele
+2  A: 

Try this :

[XmlElement(IsNullable = false)]
public Nullable<DateTime> MyDateTime { get; set }

With IsNullable set to false, the property won't be serialized when the value is null


UPDATE : OK, this doesn't work... here's an alternative that should give the desired result :

[XmlIgnore]
public Nullable<DateTime> MyDateTime { get; set }

[XmlElement(ElementName = "MyDateTime", IsNullable = false)]
public string MyDateTimeXml
{
    get
    {
        if (MyDateTime.HasValue)
            return XmlConvert.ToString(MyDateTime.Value, XmlDateTimeSerializationMode.Unspecified);
        else
            return null;
    }
    set
    {
        if (value != null)
            MyDateTime = XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.Unspecified);
        else
            MyDateTime = null;
    }
}

A bit longer, but still easier than implementing IXmlSerializable ;)


UPDATE 2 :

I just stumbled upon this question, where Marc gives an excellent answer. Just add a ShouldSerializeMyDateTime method to your class :

public bool ShouldSerializeMyDateTime()
{
    return MyDateTime.HasValue;
}

Apparently this is an undocumented feature of XML serialization... You can also use a property named MyDateTimeSpecified

Thomas Levesque
This doesn't work: `System.InvalidOperationException: IsNullable may not be set to 'false' for a Nullable<System.DateTime> type. Consider using 'System.DateTime'`.
Simon Steele
see my updated answer
Thomas Levesque
Why you have used public string MyDateTimeXML()
MyDateTime will not be serialized (`XmlIgnore`), instead MyDateTimeXML will be serialized in an element named "MyDateTime". Since it is of type string, it can be null, so it won't be serialized if it's null. This trick also allows better control on the formatting of a property
Thomas Levesque
I've used the 2nd technique before as well, but to serialize a TimeSpan if I recall correctly.
Robert Paulson
For mine to compile I tweaked the line:if (MyDateTime.HasValue) return XmlConvert.ToString(MyDateTime, XmlDateTimeSerializationMode.Unspecified); toif (MyDateTime.HasValue) return XmlConvert.ToString(MyDateTime.Value, XmlDateTimeSerializationMode.Unspecified);
Perhentian
@Perhenthian : you're right, I'll update the code accordingly. Thanks !
Thomas Levesque