Format de date ASP.NET MVC JsonResult

J’ai une action de contrôleur qui renvoie simplement un résultat JsonResult de mon modèle. Donc, dans ma méthode, j’ai quelque chose comme ce qui suit:

return new JsonResult(myModel); 

Cela fonctionne bien, sauf pour un problème. Il y a une propriété date dans le modèle et cela semble être retourné dans le résultat Json comme ceci:

 "\/Date(1239018869048)\/" 

Comment dois-je gérer les dates afin qu’elles soient renvoyées dans le format requirejs? Ou comment gérer ce format ci-dessus dans un script?

Juste pour développer la réponse de casperOne .

La spécification JSON ne prend pas en compte les valeurs de date. MS devait passer un appel et le chemin choisi consistait à exploiter une petite astuce dans la représentation javascript des chaînes: le littéral chaîne “/” est identique à “\ /” et un littéral chaîne ne sera jamais sérialisé en ” \ / “(même” \ / “doit être mappé sur” \\ / “).

Voir http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2 pour une meilleure explication (allez jusqu’à “Des littéraux JavaScript au JSON”).

L’un des points sensibles de JSON est l’absence de littéral date / heure. Beaucoup de gens sont surpris et déçus d’apprendre cela lorsqu’ils rencontrent JSON pour la première fois. L’explication simple (consoler ou non) de l’absence d’un littéral date / heure est que JavaScript n’en a jamais eu non plus: le support des valeurs de date et heure en JavaScript est entièrement fourni via l’object Date. Par conséquent, la plupart des applications utilisant JSON comme format de données ont généralement tendance à utiliser une chaîne ou un nombre pour exprimer les valeurs de date et d’heure. Si une chaîne est utilisée, vous pouvez généralement vous attendre à ce qu’elle soit au format ISO 8601. Si un nombre est utilisé, la valeur désigne généralement le nombre de millisecondes en temps coordonné universel (UTC) depuis l’époque, où l’époque est définie comme étant minuit le 1er janvier 1970 (UTC). Encore une fois, ceci est une simple convention et ne fait pas partie de la norme JSON. Si vous échangez des données avec une autre application, vous devrez vérifier sa documentation pour voir comment elle encode les valeurs de date et d’heure dans un littéral JSON. Par exemple, Microsoft ASP.NET AJAX de Microsoft n’utilise aucune des conventions décrites. Au lieu de cela, il code les valeurs .NET DateTime sous forme de chaîne JSON, où le contenu de la chaîne est / Date (ticks) / et où ticks représente des millisecondes depuis le début du temps (UTC). Ainsi, le 29 novembre 1989 à 4:55:30 du matin, en UTC, le code “\ / Date (628318530718) \ /” est codé.

Une solution serait simplement de l’parsingr:

 value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10)); 

Toutefois, j’ai entendu dire qu’il existe un paramètre permettant au sérialiseur de générer des objects DateTime avec la new Date(xxx) syntaxe new Date(xxx) . Je vais essayer de creuser ça.


Le second paramètre de JSON.parse() accepte une fonction JSON.parse() comment la valeur produite à l’origine par, avant d’être renvoyée.

Voici un exemple pour la date:

 var parsed = JSON.parse(data, function(key, value) { if (typeof value === 'ssortingng') { var d = /\/Date\((\d*)\)\//.exec(value); return (d) ? new Date(+d[1]) : value; } return value; }); 

Voir la documentation de JSON.parse ()

Voici ma solution en Javascript – très semblable à celle de JPot, mais plus courte (et peut-être un peu plus rapide):

 value = new Date(parseInt(value.substr(6))); 

“value.substr (6)” supprime la partie “/ Date (“) et la fonction parseInt ignore les caractères non numériques qui apparaissent à la fin.

EDIT: J’ai volontairement laissé de côté la base (le deuxième argument à parsingr); voir mon commentaire ci-dessous . Veuillez également noter que les dates ISO-8601 sont préférables à cet ancien format. Ce format ne doit donc généralement pas être utilisé pour de nouveaux développements. Voir l’excellente bibliothèque Json.NET pour une excellente alternative qui sérialise les dates en utilisant le format ISO-8601.

Pour les dates JSON formatées ISO-8601, il suffit de passer la chaîne dans le constructeur Date:

 var date = new Date(jsonDate); //no ugly parsing needed; full timezone support 

Il y a pas mal de réponses pour gérer le côté client, mais vous pouvez modifier le côté serveur de sortie si vous le souhaitez.

Il y a plusieurs façons d’aborder cela, je vais commencer par les bases. Vous devrez sous-classer la classe JsonResult et substituer la méthode ExecuteResult. À partir de là, vous pouvez adopter différentes approches pour modifier la sérialisation.

Approche 1: l’ implémentation par défaut utilise le JsonScriptSerializer . Si vous consultez la documentation, vous pouvez utiliser la méthode RegisterConverters pour append des convertisseurs JavaScript personnalisés. Il existe toutefois quelques problèmes avec ceci: JavaScriptConverter sérialise dans un dictionnaire, c’est-à-dire qu’il prend un object et se sérialise dans un dictionnaire Json. Pour que l’object soit sérialisé en une chaîne, il faut un peu de piratage, voir l’ article . Ce hack va également échapper à la chaîne.

 public class CustomJsonResult : JsonResult { private const ssortingng _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!Ssortingng.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { JavaScriptSerializer serializer = new JavaScriptSerializer(); // Use your custom JavaScriptConverter subclass here. serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter }); response.Write(serializer.Serialize(Data)); } } } 

Approche 2 (recommandée): La deuxième approche consiste à commencer avec le JsonResult substitué et à utiliser un autre sérialiseur Json, dans mon cas le sérialiseur Json.NET . Cela ne nécessite pas le piratage de l’approche 1. Voici ma mise en œuvre de la sous-classe JsonResult:

 public class CustomJsonResult : JsonResult { private const ssortingng _dateFormat = "yyyy-MM-dd HH:mm:ss"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; if (!Ssortingng.IsNullOrEmpty(ContentType)) { response.ContentType = ContentType; } else { response.ContentType = "application/json"; } if (ContentEncoding != null) { response.ContentEncoding = ContentEncoding; } if (Data != null) { // Using Json.NET serializer var isoConvert = new IsoDateTimeConverter(); isoConvert.DateTimeFormat = _dateFormat; response.Write(JsonConvert.SerializeObject(Data, isoConvert)); } } } 

Exemple d’utilisation:

 [HttpGet] public ActionResult Index() { return new CustomJsonResult { Data = new { users=db.Users.ToList(); } }; } 

Crédits supplémentaires: James Newton-King

Moment.js est une bibliothèque datetime étendue qui prend également en charge cette fonctionnalité. http://momentjs.com/docs/#/parsing/asp-net-json-dates/

ex: moment (“/ Date (1198908717056-0700) /”)

Cela pourrait aider. sortie de plongeur

Utilisation de jQuery pour convertir automatiquement les dates avec $.parseJSON

Remarque : cette réponse fournit une extension jQuery qui ajoute la prise en charge automatique du format de date ISO et .net.

Puisque vous utilisez Asp.net MVC, je suppose que vous utilisez jQuery côté client. Je vous suggère de lire ce billet de blog qui explique comment utiliser $.parseJSON pour convertir automatiquement les dates pour vous.

Code prend en charge les dates au format Asp.net telles que celles que vous avez mentionnées, ainsi que les dates au format ISO. Toutes les dates seront automatiquement formatées pour vous en utilisant $.parseJSON() .

J’ai constaté que la création d’un nouveau JsonResult et le renvoi de résultats non satisfaisants – avoir à remplacer tous les appels pour return Json(obj) avec le return new MyJsonResult { Data = obj } est une return new MyJsonResult { Data = obj } .


Alors j’ai pensé, pourquoi ne pas simplement détourner le JsonResult utilisant un ActionFilter :

 public class JsonNetFilterAtsortingbute : ActionFilterAtsortingbute { public override void OnActionExecuted(ActionExecutedContext filterContext) { if (filterContext.Result is JsonResult == false) { return; } filterContext.Result = new JsonNetResult( (JsonResult)filterContext.Result); } private class JsonNetResult : JsonResult { public JsonNetResult(JsonResult jsonResult) { this.ContentEncoding = jsonResult.ContentEncoding; this.ContentType = jsonResult.ContentType; this.Data = jsonResult.Data; this.JsonRequestBehavior = jsonResult.JsonRequestBehavior; this.MaxJsonLength = jsonResult.MaxJsonLength; this.RecursionLimit = jsonResult.RecursionLimit; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } var isMethodGet = ssortingng.Equals( context.HttpContext.Request.HttpMethod, "GET", SsortingngComparison.OrdinalIgnoreCase); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && isMethodGet) { throw new InvalidOperationException( "GET not allowed! Change JsonRequestBehavior to AllowGet."); } var response = context.HttpContext.Response; response.ContentType = ssortingng.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) { response.ContentEncoding = this.ContentEncoding; } if (this.Data != null) { response.Write(JsonConvert.SerializeObject(this.Data)); } } } } 

Ceci peut être appliqué à toute méthode renvoyant un JsonResult pour utiliser JSON.Net à la place:

 [JsonNetFilter] public ActionResult GetJson() { return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet) } 

qui répondra avec

 {"hello":"2015-03-09T00:00:00+00:00"} 

comme voulu!


Vous pouvez, si cela ne vous dérange pas d’appeler la comparaison is à chaque demande, append ceci à votre FilterConfig :

 // ... filters.Add(new JsonNetFilterAtsortingbute()); 

et tous vos JSON seront maintenant sérialisés avec JSON.Net au lieu du JavaScriptSerializer intégré.

La communication Ajax entre le client et le serveur implique souvent des données au format JSON. Bien que JSON fonctionne bien pour les chaînes, les nombres et les booléens, il peut poser certaines difficultés pour les dates en raison de la façon dont ASP.NET les sérialise. Comme il n’y a pas de représentation particulière pour les dates, elles sont sérialisées en tant que chaînes simples. En guise de solution, le mécanisme de sérialisation par défaut de ASP.NET Web Forms et de MVC sérialise les dates sous une forme spéciale – / Date (ticks) / – où ticks correspond au nombre de millisecondes depuis le 1er janvier 1970.

Ce problème peut être résolu de 2 manières:

côté client

Convertissez la chaîne de date reçue en un nombre et créez un object de date à l’aide du constructeur de la classe de date avec les ticks en paramètre.

 function ToJavaScriptDate(value) { var pattern = /Date\(([^)]+)\)/; var results = pattern.exec(value); var dt = new Date(parseFloat(results[1])); return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear(); 

}

du côté serveur

La solution précédente utilise un script côté client pour convertir la date en object Date JavaScript. Vous pouvez également utiliser un code côté serveur qui sérialise les instances .NET DateTime au format de votre choix. Pour accomplir cette tâche, vous devez créer votre propre ActionResult, puis sérialiser les données comme vous le souhaitez.

référence: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

J’ai eu le même problème et au lieu de renvoyer la valeur de date réelle, je viens d’utiliser ToSsortingng (“jj MMM aaaa”). Ensuite, dans mon javascript, j’ai utilisé new Date (datevalue), datevalue pouvant être “01 janv. 2009”.

Voir ce fil:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

Fondamentalement, bien que le format Date () soit valide javascript, ce n’est pas valide JSON (il y a une différence). Si vous voulez l’ancien format, vous devrez probablement créer une façade et transformer la valeur vous-même, ou trouver un moyen d’obtenir le sérialiseur pour votre type dans JsonResult et lui demander d’utiliser un format personnalisé pour les dates.

Pas la manière la plus élégante mais cela a fonctionné pour moi:

 var ms = date.subssortingng(6, date.length - 2); var newDate = formatDate(ms); function formatDate(ms) { var date = new Date(parseInt(ms)); var hour = date.getHours(); var mins = date.getMinutes() + ''; var time = "AM"; // find time if (hour >= 12) { time = "PM"; } // fix hours format if (hour > 12) { hour -= 12; } else if (hour == 0) { hour = 12; } // fix minutes format if (mins.length == 1) { mins = "0" + mins; } // return formatted date time ssortingng return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time; } 

J’ai travaillé sur une solution à ce problème car aucune des réponses ci-dessus ne m’a vraiment aidé. Je travaillais avec le calendrier de la semaine jQuery et j’avais besoin de dates pour avoir des informations de fuseau horaire sur le serveur et localement sur la page. Après avoir fouillé un peu, j’ai trouvé une solution qui pourrait aider les autres.

J’utilise asp.net 3.5, vs 2008, asp.net MVC 2 et le calendrier de la semaine jQuery,

Premièrement, j’utilise une bibliothèque écrite par Steven Levithan qui aide à gérer les dates du côté client, la bibliothèque de dates de Steven Levithan . Le format isoUtcDateTime est parfait pour ce dont j’avais besoin. Dans mon appel AJAX jquery, j’utilise la fonction de formatage fournie avec la bibliothèque avec le format isoUtcDateTime et lorsque l’appel ajax touche ma méthode d’action, le type datetime est local et reflète l’heure du serveur.

Lorsque j’envoie des dates sur ma page via AJAX, je les envoie sous forme de chaînes de texte en les formatant avec “jj, jj MMM aaaa HH ‘:’ mm ‘:’ ss ‘GMT’zzzz”. Ce format est facilement converti côté client en utilisant

 var myDate = new Date(myReceivedDate); 

Voici ma solution complète moins la source de Steve Levithan, que vous pouvez télécharger:

Manette:

 public class HomeController : Controller { public const ssortingng DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz"; public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } public JsonResult GetData() { DateTime myDate = DateTime.Now.ToLocalTime(); return new JsonResult { Data = new { myDate = myDate.ToSsortingng(DATE_FORMAT) } }; } public JsonResult ReceiveData(DateTime myDate) { return new JsonResult { Data = new { myDate = myDate.ToSsortingng(DATE_FORMAT) } }; } } 

Javascript:

  

J’espère que cet exemple rapide aidera d’autres personnes dans la même situation que celle dans laquelle je me trouvais. À l’heure actuelle, il semble très bien fonctionner avec la sérialisation JSON de Microsoft et maintient mes dates exactes dans les fuseaux horaires.

La meilleure façon de gérer les dates dans knockoutjs est d’utiliser la bibliothèque de moments et de gérer les dates comme Boss. Vous pouvez facilement traiter des dates telles que / Date (-62135578800000) /. Pas besoin de vous soucier de la façon dont votre date de sérialisation dans le contrôleur

 function jsonToDate(date,format) { return moment(date).format(format); } 

l’utiliser comme

 var formattedDate = jsonToDate(date,'MM/DD/YYYY') 

momentjs prend en charge de nombreux formats de date / heure et des fonctions utilitaires sur les dates

Formatez la date dans la requête.

 var _myModel = from _m in model.ModelSearch(word) select new { date = ((DateTime)_m.Date).ToShortDateSsortingng() }; 

Le seul problème avec cette solution est que vous n’obtiendrez aucun résultat si AUCUNE des valeurs de date n’est nulle. Pour contourner ce problème, vous pouvez soit insérer des instructions conditionnelles dans votre requête AVANT de sélectionner la date qui ignore les dates nulles, soit configurer une requête pour obtenir tous les résultats, puis parcourir toutes ces informations à l’aide d’une boucle foreach et atsortingbuer une valeur. à toutes les dates nulles AVANT de faire votre nouvelle commande SELECT.

Exemple des deux:

 var _test = from _t in adc.ItemSearchTest(word) where _t.Date != null select new { date = ((DateTime)_t.Date).ToShortDateSsortingng() }; 

La deuxième option nécessite entièrement une autre requête afin que vous puissiez affecter des valeurs à toutes les valeurs nulles. Cette boucle et la boucle foreach doivent être AVANT votre requête qui sélectionne les valeurs.

 var _testA = from _t in adc.ItemSearchTest(word) select _i; foreach (var detail in _testA) { if (detail.Date== null) { detail.Date= Convert.ToDateTime("1/1/0001"); } } 

Juste une idée que j’ai trouvée plus facile que tous les exemples en javascript.

Vous pouvez utiliser cette méthode:

 Ssortingng.prototype.jsonToDate = function(){ try{ var date; eval(("date = new " + this).replace(/\//g,'')); return date; } catch(e){ return new Date(0); } }; 

ajoutez le plugin jquery ui dans votre page.

 function JsonDateFormate(dateFormate, jsonDateTime) { return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1))); }; 

Il retourne le format de date du serveur. Vous devez définir votre propre fonction.

 function jsonDateFormat(jsonDate) { // Changed data format; return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt"); 

};

Voici du code JavaScript que j’ai écrit qui définit une valeur partir d’une date passée à partir d’ASP.NET MVC.

  var setDate = function (id, d) { if (d !== undefined && d !== null) { var date = new Date(parseInt(d.replace("/Date(", "").replace(")/", ""), 10)); var day = ('0' + date.getDate()).slice(-2); var month = ('0' + (date.getMonth() + 1)).slice(-2); var parsedDate = date.getFullYear() + "-" + (month) + "-" + (day); $(id).val(parsedDate); } }; 

Vous appelez cette fonction comme suit:

 setDate('#productCommissionStartDate', data.commissionStartDate); 

Où commissionStartDate est la date JSON transmise par MVC.

Pas pour rien, mais il y a un autre moyen. Commencez par construire votre requête LINQ. Ensuite, créez une requête du résultat énuméré et appliquez le type de mise en forme qui vous convient.

 var query = from t in db.Table select new { t.DateField }; var result = from c in query.AsEnumerable() select new { c.DateField.toSsortingng("dd MMM yyy") }; 

Je dois dire que l’étape supplémentaire est ennuyeuse, mais cela fonctionne bien.

Ce qui a fonctionné pour moi a été de créer un modèle de vue contenant la propriété date sous forme de chaîne. Affectation de la propriété DateTime à partir du modèle de domaine et appel de la propriété .ToSsortingng () sur la propriété date lors de l’atsortingbution de la valeur à viewmodel.

Un résultat JSON d’une méthode d’action MVC renverra la date dans un format compatible avec la vue.

Voir le modèle

 public class TransactionsViewModel { public ssortingng DateInitiated { get; set; } public ssortingng DateCompleted { get; set; } } 

Modèle de domaine

 public class Transaction{ public DateTime? DateInitiated {get; set;} public DateTime? DateCompleted {get; set;} } 

Méthode d’action du contrôleur

 public JsonResult GetTransactions(){ var transactions = _transactionsRepository.All; var model = new List(); foreach (var transaction in transactions) { var item = new TransactionsViewModel { ............... DateInitiated = transaction.DateInitiated.ToSsortingng(), DateCompleted = transaction.DateCompleted.ToSsortingng(), }; model.Add(item); } return Json(model, JsonRequestBehavior.AllowGet); } 

Remplacez les contrôleurs Json / JsonResult pour renvoyer JSON.Net:

Cela fonctionne un régal

Ennuyant, n’est-ce pas?

Ma solution consistait à modifier mon service WCF pour qu’il renvoie DateTimes dans un format plus lisible (non Microsoft). Remarquez ci-dessous, le ” UpdateDateOriginal “, qui est le format par défaut des dates de WCF, et mon ” UpdateDate “, qui est formaté de manière plus lisible.

entrez la description de l'image ici

Voici comment le faire:

Changer le format de date WCF

J’espère que cela t’aides.

Le plus facile:

var milisegundos = parseInt (data.replace (“/ Date (“, “”) .replace (“) /”, “”));
Var newDate = new Date (milisegundos). toLocaleDateSsortingng (“en-UE”);