Использование JSON.NET для возврата ActionResult

Я пытаюсь написать метод С#, который будет сериализовать модель и вернуть результат 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);
    }

Я получил следующий результат JSON, когда я перехожу к Words/Read в 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}

Я думаю, что экранированные кавычки - это проблема, возникающая при двойном сериализации объекта. Из других вопросов: Выход WCF JSON получает ненужные кавычки и обратные слэши

Это определенно похоже, что я дважды сериализую свой объект, так как я сначала сериализую с использованием JSON.NET, а затем передаю свой результат в функцию Json(). Мне нужно вручную сериализовать, чтобы избежать ссылок, но я думаю, что My View требует ActionResult.

Как я могу вернуть ActionResult здесь? Мне нужно, или я могу просто вернуть строку?

Ответ 1

Я нашел аналогичный вопрос stackoverflow: Json.Net и ActionResult

Ответ там предложил использовать

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

Это похоже на мою очень простую страницу.

Ответ 2

Вместо сериализации с использованием JSON.NET и последующего вызова Json(), почему бы вместо этого не переопределить метод Json() в вашем контроллере (или, возможно, базовый контроллер для повышения его повторного использования)?

Это вытащили из этого блога post.

В контроллере (или базовом контроллере):

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

И определение для 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());
        }
    }
}

Таким образом, когда вы вызываете Json() в своем контроллере, вы автоматически получите сериализацию JSON.NET, которую вы хотите.