I'm trying to write a C# method that will serialize a model and return a JSON result. Here's my 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);
    }

I got the following JSON result when I go to 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}

I think the \" escaped quotes are a problem that occurs when you double serialize an object. From other questions: WCF JSON output is getting unwanted quotes & backslashes added

It definitely looks like I'm double serializing my object, since I first serialize using JSON.NET and then pass my result into the Json() function. I need to manually serialize to avoid referenceloops, but I think my View needs an ActionResult.

How can I return an ActionResult here? Do I need to, or can I just return a string?

有帮助吗?

解决方案

I found a similar stackoverflow question: Json.Net And ActionResult

The answer there suggested using

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

That seems to work on my very simple page.

其他提示

Instead of serializing using JSON.NET and then calling Json(), why not instead override the Json() method in your controller (or perhaps a base controller to enhance its re-usability)?

This is pulled from this blog post.

In your controller (or base 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
    };
}

And the definition for 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());
        }
    }
}

By doing this, when you call Json() in your controller, you will automatically get the JSON.NET serializing you want.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top