views:

49

answers:

2

The DateTimeOffset property I have in this class doesn't get rendered when the data is represented as Xml. What do I need to do to tell the Xml serialization to render that proper as a DateTime or DateTimeOffset?

[XmlRoot("playersConnected")]
public class PlayersConnectedViewData
{
    [XmlElement("playerConnected")]
    public PlayersConnectedItem[] playersConnected { get; set; }
}

[XmlRoot("playersConnected")]
public class PlayersConnectedItem
{
    public string name { get; set; }
    public DateTimeOffset connectedOn { get; set; }  // <-- This property fails.
    public string server { get; set; }
    public string gameType { get; set; }
}

and some sample data...

<?xml version="1.0" encoding="utf-8"?>
<playersConnected 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <playerConnected>
    <name>jollyroger1000</name>
    <connectedOn />
    <server>log1</server>
    <gameType>Battlefield 2</gameType>
  </playerConnected>
</playersConnected>

Update

I'm hoping there might be a way through an Attribute which I can decorate on the property...

Bonus Question

Any way to get rid of those two namespaces declared in the root node? Should I?

+1  A: 

one way to solve this problem is have your class implement the interface IXmlSerializable. Implementing this interface forces the serializer to call the 'overridden' WriteXml and ReadXml mathods.

something like that :

public void WriteXml(XmlWriter writer)

{

writer.WriteStartElement("playersConnected"); writer.WriteElementString("name", Name); wrtier.WriteElementString("connected-on" , ConnectedOn.ToString("dd.MM.yyyy HH:mm:ss")); etc... }`

and when you read it :

DateTimeOffset offset; if(DateTimeoffset.TryParse(reader.Value,out offset)) connectedOn = offset;

it is a hassle but i cannot thing of any other way. also this solution gives you full control on your serialization process(this is the upside)

if you like this solution and want the complete one please comment and i will write it down

regarding the namespaces - i don't think you can get rid of it(i won't get the bonus score probably).

Itai Zolberg
A: 

I've ended up just doing this...

Added the two extension methods ...

public static double ToUnixEpoch(this DateTimeOffset value)
{
    // Create Timespan by subtracting the value provided from 
    //the Unix Epoch then return the total seconds (which is a UNIX timestamp)
    return (double)((value - new DateTime(1970, 1, 1, 0, 0, 0, 0)
        .ToLocalTime())).TotalSeconds;
}

public static string ToJsonString(this DateTimeOffset value)
{
    return string.Format("\\/Date({0})\\/", value.ToUnixEpoch());
}

Modified the ViewData class...

[XmlRoot("playersConnected")]
public class PlayersConnectedItem
{
    public string name { get; set; }
    public string connectedOn { get; set; }
    public string server { get; set; }
    public string gameType { get; set; }
}

Changed how I set the viewdata properties...

var data = (from q in connectedPlayerLogEntries
            select new PlayersConnectedItem
                       {
                           name = q.ClientName,
                           connectedOn =  q.CreatedOn.ToJsonString(),
                           server = q.GameFile.UniqueName,
                           gameType = q.GameFile.GameType.Description()
                        });

Done. Not sure if that's the best way .. but now that viewdata property has the same values for either Json or Xml.

Pure.Krome