Ah, dates. Simple little things, really, especially when working with .Net and JavaScript, right?
Well, sort of. See, Microsoft decided that when serializing DateTime objects, they should be formatted like this:
"\/Date(12345678)\/". Unfortunately, without running eval() on that, that format is useless.
I've never really had this issue before, because when working with dates on the client side, I always use strings.
So why the issue now?
Because, along with using MVC, I decided to use the Entity Framework, which made it really easy to return a bunch of objects from the database:
return Json(db.Tasks.ToList());In the past, this would have been more like:
DataTable dt = new DataTable();
dt.Load(command.ExecuteReader());
return dt.Rows.Cast<DataRow>().Select(
r =>
new
{
id = (int) r["id"],
name = (string) r["name"],
date = ((DateTime) r["date"]).ToString("yyyy-MM-dd")
});
Now, I could simply go on using the select statement, but I just couldn't bear the thought of doing that everytime I had to work with dates (since that is all the time). So instead I wrote a custom Json serializer derived from JsonResult. I've uploaded the source code (link at bottom), but the real magic is in these lines:
public bool HasDates { get; set; }
public override void ExecuteResult(ControllerContext context)
{
//... a bunch of code ...
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(HasDates ? FixDates(serializer.Serialize(Data)) : serializer.Serialize(Data));
}
}
public string FixDates(string data)
{
var matches = Regex.Matches(data, @"\\/Date\((?<ticks>\d+)?\)\\/").Cast<Match>().ToArray();
for (int i = matches.Length - 1; i >= 0; i--)
{
var match = matches[i];
data = data.Remove(match.Index, match.Length)
.Insert(match.Index,
new DateTime(1970, 1, 1).AddMilliseconds(long.Parse(match.Groups["ticks"].Value))
.ToString("yyyy-MM-dd HH:mm:ss"));
}
return data;
}
The code simply loops through the standard serialized result and replaces any MS-formatted date strings with my kind of date string (yyyy-MM-dd HH:mm:ss eg. "2011-11-21 19:48:13").Updated return call:
return new ProperJsonResult() { HasDates = true, Data = db.Tasks.ToList() };
Click here to download ProperJsonResult.cs
No comments:
Post a Comment