web-dev-qa-db-fra.com

Utilisation de JSON.NET pour renvoyer ActionResult

J'essaie d'écrire une méthode C # qui sérialisera un modèle et renverra un résultat JSON. Voici mon code:

    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);
    }

J'ai obtenu le résultat JSON suivant lorsque je vais dans Words/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}

Je pense que les citations échappées sont un problème qui survient lorsque vous sérialisez un objet en double. Autres questions: La sortie WCF JSON reçoit des guillemets non désirés et des barres obliques inverses ajoutées

On dirait bien que je suis en train de sérialiser mon objet en double, puisque j'ai tout d'abord sérialisé en utilisant JSON.NET, puis que je passe mon résultat à la fonction Json (). Je dois sérialiser manuellement pour éviter les références, mais je pense que ma vue nécessite un ActionResult.

Comment puis-je retourner un ActionResult ici? Dois-je ou dois-je simplement renvoyer une chaîne?

49
hubatish

J'ai trouvé une question similaire stackoverflow: Json.Net And ActionResult

La réponse a suggéré d'utiliser

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

Cela semble fonctionner sur ma page très simple.

77
hubatish

Au lieu de sérialiser à l'aide de JSON.NET puis d'appeler Json(), pourquoi ne pas remplacer la méthode Json() dans votre contrôleur (ou peut-être un contrôleur de base pour améliorer sa réutilisation)?

Ceci est tiré de ceci blog post .

Dans votre contrôleur (ou contrôleur de base):

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
    };
}

Et la définition de 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
        && "GET".Equals(
                context.HttpContext.Request.HttpMethod,
                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());
        }
    }
}

Ce faisant, lorsque vous appelez Json() dans votre contrôleur, vous obtiendrez automatiquement le numéro de série JSON.NET souhaité.

66
Sven Grosen