2013-04-11 7 views
14

Io uso ASP.NET MVC di inviare JSON da jQuery, e un po 'indietro JSON, usando questa piccola funzione di libreria:jQuery messaggio JSON non riesce quando si ritorna nulla da ASP.NET MVC

(function($) { 
    $.postJson = function(url, data) { 
     return $.ajax({ 
      url: url, 

      data: JSON.stringify(data), 
      type: 'POST', 
      dataType: 'json', 
      contentType: 'application/json; charset=utf-8' 
     }); 
    }; 
})(jQuery); 

Così, ovviamente, ti chiamo questo come:

$('#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 e ASP.NET MVC 4 sostegno presentare lato delle cose (prima che avevi bisogno di estendere ASP.NET MVC per gestire la presentazione JSON), ma il problema che sto correndo in è al ritorno. Sul controller torno spesso nulla da dire fondamentalmente "Successo, niente altro da dire", come:

[HttpPost] 
public JsonResult DoSomething(string Prop1, string Prop2) 
{ 
    if (doSomething(Prop1, Prop2) 
     return Json(null); // Success 

    return Json(new { Message = "It didn't work for the following reasons" }); 
} 

Io uso questo schema spesso e funziona benissimo - il mio successo/callback fatto viene chiamato e tutto va bene. Ma recentemente ho aggiornato ASP.NET MVC e jQuery, e ha smesso di funzionare - invece il mio callback fallito viene chiamato ogni volta che ho return Json(null);. Inoltre, ho ispezionato la risposta e lo statusCode che viene restituito è in effetti 200, quindi il server non ha esito negativo - jQuery sta semplicemente dicendo che lo è.

+1

BTW globale '$ (document) .ajaxError ...' 'spettacoli in exception.message':" ** Fine imprevista dell'input ** "quando viene restituito' Json (null) '(solo per dirlo, non mi ha aiutato a trovare il motivo del problema). – Slauma

risposta

35

Il problema è stato causato dall'aggiornamento da jQuery 1.8 a 1.9. In jQuery 1.7 e 1.8, questo in MVC:

return Json(null); 

è stato accettato come JSON valido e interpretato come null. Tecnicamente, questo invia una stringa vuota al client con HTTP 200, e questo è abbastanza buono per jQuery < 1.9.

Ma ora (stiamo usando jQuery 1.9.1), tenta di analizzare la stringa vuota come JSON, il parser JSON di jQuery genera un'eccezione sulla stringa vuota e fa scattare una catena di codice che termina con una callback fail() .

Una soluzione è passare invece questo ritorno dal server in caso di successo, senza altre informazioni:

return Json(new{}); 

che passa radunare con JSON parser di jQuery e tutto va bene. Questo funziona anche:

return Json(true); 


Aggiornamento

Musa Le note sotto questo comportamento MVC sembra rotto. Questo separate Stack Overflow answer to Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible? spiega come far sì che MVC restituisca null per Json(null) - fondamentalmente, usa Json.NET invece del serializer JSON incorporato di ASP.NET MVC. Questa è la soluzione alla fine ho finito per usare.

Per risolvere questo problema è necessario utilizzare una versione leggermente modificata di tale risposta: il codice è riportato di seguito. Fondamentalmente, non includere la verifica dell'istruzione if per null prima di passare alla serializzazione, o sei di nuovo nella stessa situazione.


Update 2

L'implementazione predefinita di ISO 8601 Le date in Json.NET rompe Internet Explorer 9 e sotto quando si tenta di analizzare con new Date(...).In altre parole, questi analizzare bene in Internet   Explorer   9:

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

Ma questo genera un'eccezione:

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

Internet   Explorer   9 di Date() implementazione non possono far fronte con qualsiasi cosa, ma esattamente tre millisecondi. Per risolvere questo problema è necessario sovrascrivere il formato della data di Json.NET per forzarlo. Incluso nel codice qui sotto.

public class JsonNetResult : JsonResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     if (context == null) 
      throw new ArgumentNullException("context"); 

     var response = context.HttpContext.Response; 

     response.ContentType = !String.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 Gist che dimostra come legare questo in un BaseController:

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

+0

'return Json (null);' la restituzione di una stringa vuota sembra rotta, dovrebbe restituire 'null' – Musa

+0

@Musa Probabilmente, anche se a questo punto potrebbe anche esserci un cambio di rottura - sono andato a scavare e sembra che sia tornato un vuoto stringa per null dai primi giorni di MVC. Sono d'accordo che potrebbe essere una soluzione più pulita a questo problema però. Questa risposta copre ciò nonostante, sebbene il codice di esempio controlli null e restituisca una stringa vuota prima che Json.Net possa ottenere un tentativo, rimuove quelle 2 righe e restituirà null non modificato. http://stackoverflow.com/a/7150912/176877 –

Problemi correlati