Jacob Stamm Jacob Stamm - 2 months ago 26
Javascript Question

Return JavaScript object literal, not JSON string, from ASP.NET MVC endpoint

For various reasons, I have switched from ASP.NET MVC's built in JSON serializer (the one that returns a

System.Web.Mvc.JsonResult
object (see edit below)) to Newtonsoft. I didn't realize until after I began testing that the former returns a JavaScript object literal, while Newtonsoft returns a JSON formatted string.

I like not having to parse JSON strings on the client side — having it already as an object literal is very convenient — but I want to stick with Newtonsoft for other technical reasons.

For example, instead of seeing this result on my client...

"{"Errors":["Please enter a valid email address."],"HasErrors":true}"


...I'd like to see this result:

{"Errors":["Please enter a valid email address."],"HasErrors":true} // no quotes


Is there a way to make Newtonsoft return JS object literals instead of strings?

EDIT



The way my question was framed wasn't the best. There's nothing wrong with the
JsonResult
type. In fact, the solution still uses it. The only problem was the default
Controller.Json
methods, which can be overridden to use Newtonsoft (Json.NET) instead of the built-in serializer.

Answer

Just write a custom JsonResult that uses Newtonsoft serializer:

Something along the lines:

public abstract class BaseController : Controller
{
    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
    {
        return new JsonNetResult
        {
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            Data = data
        };
    }

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

JsonNetResult.cs:

using System;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;

public class JsonNetResult : JsonResult
{   
    public JsonSerializerSettings SerializerSettings { get; set; }
    public Formatting Formatting { get; set; }

    public JsonNetResult()
    {
        Formatting = Formatting.None;
        SerializerSettings = new JsonSerializerSettings();
        JsonRequestBehavior = JsonRequestBehavior.DenyGet;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet
            && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty(ContentType)
                                    ? ContentType
                                    : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        if (Data != null)
        {
            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };

            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);

            writer.Flush();
        }
    }
}

Credit: https://gist.github.com/jpoehls/1424538