Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override XML Serialization Method

Tags:

c#

.net

xml

I'm having trouble trying to customize the way DateTime variables are serialized in my objects. I want it to be output as 2011-09-26T13:00:00Z but when I override the GetObjectData() function as I believe is the way to do this, no XML data is output for them at all.

    [DataContract(Namespace = "")]
    [XmlRootAttribute(Namespace = "http://www.w3.org/2005/Atom", ElementName = "feed")]
    public class GCal
    {
            [XmlNamespaceDeclarations]
            public XmlSerializerNamespaces _xsns = new XmlSerializerNamespaces();

            [XmlElement(ElementName = "entry")]
            public Collection<MMU.Calendar.gCalEvent> items = new Collection<MMU.Calendar.gCalEvent>();

/*some other elements*/
    }

    public class gCalEvent
    {
            [XmlElement(Namespace = "http://schemas.google.com/g/2005")]
            public gdEvent when = new gdEvent();

/*some other elements*/
    }

    public class gdEvent : ISerializable
    {
            [XmlAttribute(AttributeName = "startTime")]
            private DateTime _startTime; 
            [XmlAttribute(AttributeName = "endTime")]
            private DateTime _endTime;

            public gdEvent(DateTime startTime, DateTime endTime)
            {
                    _startTime = startTime;
                    _endTime = endTime;
            }

            public gdEvent()
            {
                    _startTime = DateTime.MinValue;
                    _endTime = DateTime.MinValue;
            }
            [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
            public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                    //needs to be in the format 2011-09-26T13:00:00Z
                    //if (_startTime != DateTime.MinValue)
                    info.AddValue("startTime", _startTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
                    //if (_endTime != DateTime.MinValue)
                    info.AddValue("endTime", _endTime.ToString("yyyy-MM-ddTHH:mm:ssZ"));
            }
    }

    GCal calendar = new GCal();
    calendar = readSwsSpreadsheet(urlToCall);
    stream = new MemoryStream();
    XmlSerializer serializer = new XmlSerializer(typeof(GCal));
    serializer.Serialize(stream, calendar);
    stream.Seek(0, SeekOrigin.Begin);
    Stream results = new MemoryStream();
    WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
    return stream;

I have tried to look this info up but there seems to be a lot about custom serializing to files but not to XML...

like image 825
ankles Avatar asked Mar 08 '12 10:03

ankles


People also ask

How do I override XML serialization for SOAP messages?

The process for overriding XML serialization of objects as SOAP messages is similar to the process for overriding standard XML serialization. For information about overriding standard XML serialization, see How to: Specify an Alternate Element Name for an XML Stream. Create an instance of the SoapAttributeOverrides class.

What is XmlSerializer in Java?

Serialization namespace. XmlSerializer is the key Framework class which is used to serialize and deserialize XML. One of the advantages of JSON over XML has been in terms of brevity over verbosity.

How to serialize an object to XML without polluting my code?

In order to serialize this object to XML, using camel casing and without polluting my code with repetitive attributes that in real life happens thousands of times (ad nauseum), I have used XML attribute overrides. These are not simple to use. I spent quite some time getting them to work. But patience pays off.

How to define classes to be serialized in XML?

Here is the code that defines the classes to be serialized: Notice the simplicity of how these classes are defined: XML attributes are only minimally present. And the property naming in the class definition follows the C# naming convention (PascalCasing), even though it will be serialized using camel casing.


2 Answers

You're trying to customize standard serialization (ISerializable) for a property type whose containing type is being serialized with XmlSerializer. You need implement the IXmlSerializable interface to customize XML Serialization. Try something like this:

public class gdEvent : IXmlSerializable
{
    private DateTime _startTime;
    private DateTime _endTime;

    public gdEvent(DateTime startTime, DateTime endTime)
    {
        _startTime = startTime;
        _endTime = endTime;
    }

    public gdEvent()
    {
        _startTime = DateTime.MinValue;
        _endTime = DateTime.MinValue;
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void WriteXml(XmlWriter writer)
    {
        if (_startTime != DateTime.MinValue)
            writer.WriteAttributeString("startTime", _startTime.ToString("yyyy-MM-ddTHH:mm:ssZ"));
        if (_endTime != DateTime.MinValue)
            writer.WriteAttributeString("endTime", _endTime.ToString("yyyy-MM-ddTHH:mm:ssZ"));
    }

    public void ReadXml(XmlReader reader)
    {
        string startTimeString = reader.GetAttribute("startTime");
        if (!string.IsNullOrEmpty(startTimeString))
        {
            _startTime = DateTime.Parse(startTimeString);
        }
        string endTimeString = reader.GetAttribute("startTime");
        if (!string.IsNullOrEmpty(endTimeString))
        {
            _endTime = DateTime.Parse(endTimeString);
        }
    }

}

like image 174
luksan Avatar answered Oct 04 '22 02:10

luksan


I had a suggestion from @craighawker to format the DateTime into a string when calling a set() method for the DateTime. Seemed the simplest method although I would like to implement it the proper way using IXMLSerializable at some point in the future to do more powerful things

 public class gdEvent
    {
    [XmlAttribute(AttributeName = "startTime")]
    private string m_startTimeOutput;
    private DateTime m_startTime; //format 2011-11-02T09:00:00Z

    [XmlAttribute(AttributeName = "endTime")]
    private string m_endTimeOutput;
    private DateTime m_endTime; //2011-11-02T10:00:00Z

    public DateTime startTime
    {
        get
        {
        return m_startTime;
        }
        set
        {
        m_startTime = value;
        m_startTimeOutput = m_startTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
        }
    }

    public DateTime endTime
    {
        get
        {
        return m_endTime;
        }
        set
        {
        m_endTime = value;
        m_endTimeOutput = m_endTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
        }
    }
like image 38
ankles Avatar answered Oct 04 '22 04:10

ankles