JQuery post JSON échoue lors du renvoi de null à partir d’ASP.NET MVC

J’utilise ASP.NET MVC pour publier du JSON à partir de jQuery, et récupère du JSON en utilisant cette petite fonction de bibliothèque:

(function($) { $.postJson = function(url, data) { return $.ajax({ url: url, data: JSON.ssortingngify(data), type: 'POST', dataType: 'json', contentType: 'application/json; charset=utf-8' }); }; })(jQuery); 

Alors évidemment, j’appellerai ceci comme:

 $('#button').click(function() { $.postJson('/controller/action', { Prop1: 'hi', Prop2: 'bye' }) .done(function(r) { alert('It worked.'); }) .fail(function(x) { alert('Fail! ' + x.status); }); }); 

ASP.NET MVC 3 et ASP.NET MVC 4 prennent en charge le côté de la soumission (avant cela, vous deviez étendre ASP.NET MVC pour gérer la soumission de JSON), mais le problème que je rencontre se trouve au retour. Sur le contrôleur, je retourne souvent null pour dire en gros “succès, rien d’autre à dire”, comme:

 [HttpPost] public JsonResult DoSomething(ssortingng Prop1, ssortingng Prop2) { if (doSomething(Prop1, Prop2) return Json(null); // Success return Json(new { Message = "It didn't work for the following reasons" }); } 

J’utilise fréquemment ce modèle et tout fonctionne correctement – mon rappel de succès / terminé est appelé et tout va bien. Mais récemment, j’ai mis à niveau ASP.NET MVC et jQuery, qui ne fonctionne plus. Mon rappel d’échec est appelé chaque fois que je return Json(null); . De plus, j’ai inspecté la réponse et le statusCode renvoyé est en réalité 200, de sorte que le serveur n’échoue pas – jQuery dit simplement que c’est le cas.

Le problème était dû à la mise à niveau de jQuery 1.8 à 1.9. Dans jQuery 1.7 et 1.8, ceci dans MVC:

 return Json(null); 

a été accepté comme JSON valide et interprété comme nul. Techniquement, cela renvoie une chaîne vide au client avec HTTP 200, ce qui est suffisant pour jQuery <1.9.

Mais maintenant (nous utilisons jQuery 1.9.1), il tente d’parsingr la chaîne vide en tant que JSON. L’parsingur JSON de jQuery lève une exception sur une chaîne vide et déclenche une chaîne de code qui se termine par un rappel fail() .

Une solution de contournement consiste à renvoyer cette information du serveur en cas de succès, sans autre information:

 return Json(new{}); 

Cela passe avec l’parsingur JSON de jQuery et tout va bien. Cela fonctionne aussi:

 return Json(true); 

Mettre à jour

Musa note ci-dessous que ce comportement de MVC semble cassé. Cette réponse distincte de débordement de stack à l’ utilisation de JSON.NET en tant que sérialiseur JSON par défaut dans ASP.NET MVC 3 est-elle possible? explique comment faire en sorte que MVC renvoie la valeur null pour Json(null) – utilisez essentiellement Json.NET au lieu du sérialiseur JSON intégré d’ASP.NET MVC. C’est la solution que j’ai finalement utilisée.

Vous devez utiliser une version légèrement modifiée de cette réponse pour résoudre ce problème – le code est ci-dessous. En gros, n’incluez pas l’instruction if qui recherche la valeur null avant de passer à la sérialisation, if vous vous retrouvez dans le même cas.

Mise à jour 2

L’implémentation par défaut d’ISO 8601 Dates dans Json.NET interrompt Internet Explorer 9 et les versions antérieures lorsqu’il tente de l’parsingr avec la new Date(...) . En d’autres termes, ceux-ci parsingnt parfaitement dans Internet Explorer 9:

 var date = new Date('2014-09-18T17:21:57.669'); var date = new Date('2014-09-18T17:21:57.600'); 

Mais cela jette une exception:

 var date = new Date('2014-09-18T17:21:57.6'); 

L’implémentation Date () d’Internet Explorer 9 ne peut s’adapter qu’à trois millisecondes exactement. Pour résoudre ce problème, vous devez remplacer le format de date Json.NET pour le forcer. Inclus dans le code ci-dessous.

 public class JsonNetResult : JsonResult { public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); var response = context.HttpContext.Response; response.ContentType = !Ssortingng.IsNullOrEmpty(ContentType) ? ContentType : "application/json"; if (ContentEncoding != null) response.ContentEncoding = ContentEncoding; var settings = new JsonSerializerSettings { Converters = new[] {new IsoDateTimeConverter { DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK" }} }; var jsonSerializer = JsonSerializer.Create(settings); jsonSerializer.Serialize(response.Output, Data); } } 

Un résumé qui montre comment lier ceci à un BaseController:

https://gist.github.com/b9chris/6991b341e89bb0a4e6d801d02dfd7730