2014-04-28 12 views
39

Ich versuche, eine C# Methode zurückgeben zu schreiben, die ein Modell serialisiert werden und ein JSON-Ergebnis zurück. Hier ist mein Code:JSON.NET Mit Action

public ActionResult Read([DataSourceRequest] DataSourceRequest request) 
    { 
     var items = db.Words.Take(1).ToList(); 
     JsonSerializerSettings jsSettings = new JsonSerializerSettings(); 
     jsSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
     var converted = JsonConvert.SerializeObject(items, null, jsSettings); 
     return Json(converted, JsonRequestBehavior.AllowGet); 
    } 

bekam ich folgende JSON Ergebnis, wenn ich Wörter gehen/Read in Chrome:

"[{\"WordId\":1,\"Rank\":1,\"PartOfSpeech\":\"article\",\"Image\":\"Upload/29/1/Capture1.PNG\",\"FrequencyNumber\":\"22038615\",\"Article\":null,\"ClarificationText\":null,\"WordName\":\"the | article\",\"MasterId\":0,\"SoundFileUrl\":\"/UploadSound/7fd752a6-97ef-4a99-b324-a160295b8ac4/1/sixty_vocab_click_button.mp3\",\"LangId\":1,\"CatId\":null,\"IsActive\":false} 

Ich denke, die \“entkommen Anführungszeichen ein Problem sind, die bei einem Doppelklick serialize auftritt ein Objekt aus anderen Fragen. WCF JSON output is getting unwanted quotes & backslashes added

Es sieht auf jeden Fall, wie ich doppelt bin mein Objekt Serialisierung, da ich mein Ergebnis in die Json() Funktion zuerst mit JSON.NET serialisiert und dann passieren muss ich manuell serialisiert. zu vermeiden d Referenceloops, aber ich denke, dass meine Ansicht ein ActionResult benötigt.

Wie kann ich eine Action hier zurückkehren? Muss ich, oder kann ich nur eine Zeichenfolge zurückgeben?

+0

Bei der Javascript-Rückgabe mache ich einfach JSON.parse (message) ;. – MiniRagnarok

+0

Du meinst Javascript zu verwenden, um die/s einfach auszupacken? Ich benutze Razor HTML-Helfer für ein bestimmtes Paket, also weiß ich nicht, wie ich das zur Arbeit bekommen würde. – hubatish

Antwort

60

fand ich eine ähnliche Frage Stackoverflow: Json.Net And ActionResult

Die Antwort gibt vorgeschlagen

return Content(converted, "application/json"); 

verwenden, die auf meine sehr einfache Seite scheint zu funktionieren.

+4

IMO beste Antwort. Einfach und macht genau das, was gefragt wurde. – pimbrouwers

+2

Wenn Sie die Header überprüfen, werden Sie sehen, dass Sie wahrscheinlich 'text/html' als Inhaltstyp haben. – Dementic

+0

Bei weitem die einfachste Lösung. Dies macht genau das, was es braucht. – user1751825

59

Anstatt mit JSON.NET zu serialisieren und dann Json() aufzurufen, überschreiben Sie stattdessen die Json() Methode in Ihrem Controller (oder vielleicht einen Basiscontroller, um die Wiederverwendbarkeit zu verbessern)?

Dies ist aus diesem Blog post gezogen.

In Ihrem Controller (oder Basis-Controller):

protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior) 
{ 
    return new JsonNetResult 
    { 
     Data = data, 
     ContentType = contentType, 
     ContentEncoding = contentEncoding, 
     JsonRequestBehavior = behavior 
    }; 
} 

Und die Definition für JsonNetResult:

public class JsonNetResult : JsonResult 
{ 
    public JsonNetResult() 
    { 
     Settings = new JsonSerializerSettings 
     { 
      ReferenceLoopHandling = ReferenceLoopHandling.Ignore, 
     }; 
    } 

    public JsonSerializerSettings Settings { get; private set; } 

    public override void ExecuteResult(ControllerContext context) 
    { 
     if (context == null) 
      throw new ArgumentNullException("context"); 
     if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) 
      throw new InvalidOperationException("JSON GET is not allowed"); 

     HttpResponseBase response = context.HttpContext.Response; 
     response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; 

     if (this.ContentEncoding != null) 
      response.ContentEncoding = this.ContentEncoding; 
     if (this.Data == null) 
      return; 

     var scriptSerializer = JsonSerializer.Create(this.Settings); 

     using (var sw = new StringWriter()) 
     { 
      scriptSerializer.Serialize(sw, this.Data); 
      response.Write(sw.ToString()); 
     } 
    } 
} 

Auf diese Weise, wenn Sie Json() in Ihrem Controller aufrufen, werden Sie automatisch das bekommen JSON.NET Serialisierung Sie wollen.

+0

Cool. Das ist ziemlich bequem , dachte ich dies mir noch erlauben würde, JSONRequestBehavior.AllowGet passieren, aber es scheint nicht ganz zu funktionieren. – hubatish

+0

um das an die Arbeit, dann würden Sie Überschreibungen 'Json() hinzufügen müssen', die in Standard-Pass Werte für die anderen Parameter. Dies ist, was die Standardimplementierung der Fall ist. –

+0

Nun, diese Linie Json (Objektdaten, string content, System.Text.Encoding Contenten, JsonRequestBehavior Verhalten) scheint zu bedeuten, ich Json tun kann (umgerechnet , JsonRequestBehavior.AllowGet), aber ich bekomme "Um GET-Anfragen zu erlauben, setze JsonRequestBehavior auf AllowGet.", Wenn ich auf die Seite gehe. – hubatish