I have a javascript function that calls an MVC controller with JSON data:
var specsAsJson = JSON.stringify(specs);
$.post('/Home/Save', { jsonData: specsAsJson });
On the server side, within the controller, I can't seem to get past this error:
/Date(1347992529530)/ is not a valid value for DateTime.
That exception happens when I call Deserialize() (third line in method below):
public ActionResult Save(string jsonData)
{
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() });
var specs = serializer.Deserialize<List<EquipmentSpecWithParameterlessConstructor>>(jsonData);
return View("Index", _allTrackerJobs);
}
I've been doing some googling, and the above code is my latest attempt to make this work (using the TimeSpanJsonConverter from here). Other approaches show sending only a date to the server, but I have a list of objects that have dates as some properties.
Is there an elegant, generally-accepted approach to solving this, or do we still need some kind of ugly work-around? What's the right way to resolve this?
=================== End of original question ===================
Edit - SOLVED by serializing using JsonConvert
See my answer below (not the crappy work-around in this question).
Edit - Crappy work-around
I created a DTO with the exact same fields as the domain object, except that I made the date fields strings so they would deserialize. Now that I can deserialize it, I'll work on getting the dates into a valid format so I can create domain objects from my DTOs.
public class EquipmentSpecDto
{
public string StartTime { get; set; }
public string EndTime { get; set; }
// more properties here
}
And I simply just used the DTO for the deserialization:
var specs = serializer.Deserialize<List<EquipmentSpecDto>>(jsonData);
Edit 2 - Converting JavaScript Dates to .NET
For completeness, and in the hopes that I save someone else an hour, this is how I was able to convert the javascript dates:
foreach (EquipmentSpecDto specDto in specDtos)
{
// JavaScript uses the unix epoch of 1/1/1970. Note, it's important to call ToLocalTime()
// after doing the time conversion, otherwise we'd have to deal with daylight savings hooey.
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
Double startMilliseconds = Convert.ToDouble(specDto.StartTime.Substring(6, 13));
Double endMilliseconds = Convert.ToDouble(specDto.EndTime.Substring(6, 13));
DateTime startTime = unixEpoch.AddMilliseconds(startMilliseconds).ToLocalTime();
DateTime endTime = unixEpoch.AddMilliseconds(endMilliseconds).ToLocalTime();
EquipmentSpec spec = new EquipmentSpec(startTime, endTime, specDto.Equipment);
specs.Add(spec);
}
I found a simple answer. In my javascript, I was serializing the data using the JavaScriptSerializer. After much googling, I found this article that shows how to serialize using JsonConvert that causes a more .NET-friendly DateTime to be used.
Old:
var specs = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ViewBag.JobSpecEquipment))
Dates look like this: Date(1348017917565)
New:
var specs = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.JobSpecEquipment));
Dates look like this: 2012-09-18T21:27:31.1285861-04:00
So the problem was really how I was serializing in the first place. Once I used JsonConvert, deserialization on the back end simply worked.