使用JSON.NET返回ActionResult

hub*_*ish 50 c# serialization json.net asp.net-mvc-5

我正在尝试编写一个C#方法,它将序列化一个模型并返回一个JSON结果.这是我的代码:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

当我转到Chrome中的Words/Read时,我得到了以下JSON结果:

"[{\"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}
Run Code Online (Sandbox Code Playgroud)

我认为\'转义引号是双重序列化对象时出现的问题.从其他问题: WCF JSON输出添加了不需要的引号和反斜杠

它看起来好像是我对我的对象进行双重序列化,因为我首先使用JSON.NET进行序列化,然后将我的结果传递给Json()函数.我需要手动序列化以避免引用循环,但我认为我的View需要一个ActionResult.

我怎样才能在这里返回一个ActionResult?我需要,还是只能返回一个字符串?

hub*_*ish 79

我发现了一个类似的stackoverflow问题: Json.Net和ActionResult

那里的答案建议使用

return Content( converted, "application/json" );
Run Code Online (Sandbox Code Playgroud)

这似乎适用于我非常简单的页面.

  • IMO最佳答案.简单而且完全符合要求. (4认同)
  • 如果你要检查标题,你会发现你可能有`text/html`作为内容类型. (2认同)

Sve*_*sen 68

而不是使用JSON.NET进行序列化然后调用Json(),为什么不改写Json()控制器中的方法(或者可能是基本控制器以增强其可重用性)?

这是从这篇博客文章中提取.

在您的控制器(或基本控制器)中:

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
    };
}
Run Code Online (Sandbox Code Playgroud)

以及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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,当您调用Json()控制器时,您将自动获得所需的JSON.NET序列化.

  • 只需为`contentType`和`contentEncoding`传入null,您将得到与默认实现相同的结果.否则为`Json()`添加一个重载只接受`data`和`behavior`,并为`contentType`和`contentEncoding`提供空值,然后用我在答案中的所有参数调用实现. (2认同)
  • JsonNetResult对AllowGet的强制执行似乎与应用于mehtod的属性是多余的 - 当我已经拥有AcceptVerbsAttribute时,我不得不冗余地启用AllowGet.需要了解如何从ControllerContext读取AcceptVerbsAttribute. (2认同)