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...
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.
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.
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.
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.
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);
}
}
}
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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With