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