asp.net-mvc-2 datetime timespan javascriptserializer

asp.net mvc 2 - JavaScriptSerializer no deserializa DateTime/TimeSpan correctamente



asp.net-mvc-2 (2)

Tener un problema donde DateTime / TimeSpan no parece deserializarse correctamente con JavaScriptSerializer. Cuando recupero el objeto después de deserializarlo, TimeSpan está vacío y si uso DateTime, los tiempos están fuera de control. Encontré este artículo pero realmente no me ayudó demasiado. http://www.west-wind.com/weblog/ShowPost.aspx?id=471402

¿Alguien tiene alguna idea? ¿Debería probar la biblioteca json.net?

public class JsonFilter : ActionFilterAttribute { public string Param { get; set; } public Type JsonDataType { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) { string inputContent; using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) { inputContent = sr.ReadToEnd(); } JavaScriptSerializer serializer = new JavaScriptSerializer(); var result = serializer.Deserialize(inputContent, JsonDataType); filterContext.ActionParameters[Param] = result; } } } public class RosterItem { public RosterItem() { comments = new List<Form.Comment>(); } public Boolean dirty { get; set; } public int id { get; set; } public int staffId { get; set; } public String description { get; set; } public int activityId { get; set; } public DateTime date { get; set; } public TimeSpan startTime { get; set; } public TimeSpan endTime { get; set; } public List<Form.Comment> comments { get; set; } } [JsonFilter(Param = "rosterItem", JsonDataType = typeof(RosterItem))] public int SaveRosterEntry(RosterItem rosterItem) { RosterEntry rosterEntry = rosterEntryRepository.GetRosterEntry(rosterItem.id); if (rosterEntry == null) { rosterEntry = new RosterEntry(); rosterEntryRepository.Add(rosterEntry); } rosterEntry.ActivityID = rosterItem.activityId; rosterEntry.StartTime = rosterItem.startTime; rosterEntry.EndTime = rosterItem.endTime; rosterEntry.RosterDate = rosterItem.date; rosterEntry.RosterEmployeeID = rosterItem.staffId; rosterEntryRepository.Save(); return rosterEntry.RosterEntryID; }



Encontré la respuesta en la siguiente publicación en GitHub:

https://github.com/NancyFx/Nancy/issues/336

Básicamente, la respuesta fue crear un nuevo TimeSpanJsonConverter que hereda de JavaScriptConverter y luego pasarlo a una instancia de su clase de serializador:

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer() serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() });

La clase completa de referencia es (escrita por GrumpyDev ):

public class TimeSpanJsonConverter : JavaScriptConverter { public override IEnumerable<Type> SupportedTypes { get { return new[] { typeof(TimeSpan) }; } } public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { return new TimeSpan( this.GetValue(dictionary, "days"), this.GetValue(dictionary, "hours"), this.GetValue(dictionary, "minutes"), this.GetValue(dictionary, "seconds"), this.GetValue(dictionary, "milliseconds")); } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { var timeSpan = (TimeSpan)obj; var result = new Dictionary<string, object> { { "days", timeSpan.Days }, { "hours", timeSpan.Hours }, { "minutes", timeSpan.Minutes }, { "seconds", timeSpan.Seconds }, { "milliseconds", timeSpan.Milliseconds } }; return result; } private int GetValue(IDictionary<string, object> dictionary, string key) { const int DefaultValue = 0; object value; if (!dictionary.TryGetValue(key, out value)) { return DefaultValue; } if (value is int) { return (int)value; } var valueString = value as string; if (valueString == null) { return DefaultValue; } int returnValue; return !int.TryParse(valueString, out returnValue) ? DefaultValue : returnValue; } }