0

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.

Community
  • 1
  • 1
Jacob Stamm
  • 1,660
  • 1
  • 29
  • 53
  • I'm not that familiar with the .NET world - is Newtonsoft on the server? Because if so, you should never be able to return a JS literal at from the server. Not in a network request, anyway. Or is that embedded somewhere in the page when it renders? – VLAZ Sep 20 '16 at 23:32
  • Can't you edit your JS file with a JSON.Parse(response) ? – Thiago Custodio Sep 20 '16 at 23:39
  • 1
    How are you creating your JSON responses and returning them from MVC using Json.Net? – Brian Rogers Sep 20 '16 at 23:43
  • @vlaz Yes, Newtonsoft is a small framework for .NET that handles everything "JSON". It sure seems like they're coming over as JS literals -- they even have a MIME type of `application/json`. But the way it's currently doing it with Newtonsoft, they're coming over as JSON strings with a MIME type of `text/html`. – Jacob Stamm Sep 20 '16 at 23:48
  • @BrianRogers when I was using MVC's built in serializer and getting the desired result, my endpoint would have something like `return Json(returnObject)` with a return type of `JsonResult`. With Newtonsoft, it looks like `JsonConvert.SerializeObject(returnObject)` with a return type of `string`. – Jacob Stamm Sep 20 '16 at 23:51
  • 1
    Can you share the code you are using to plug in Json.NET? Is it similar to [Using JSON.NET to return ActionResult](https://stackoverflow.com/questions/23348262/using-json-net-to-return-actionresult) or [Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?](https://stackoverflow.com/questions/7109967)? Json.NET doesn't serialize objects by surrounding them with quotes so likely something is going wrong with how Json.NET is being plugged in. – dbc Sep 21 '16 at 00:13
  • @dbc I doubt it's an implementation problem. I started a basic MVC 5 project in Visual Studio, then simply downloaded the Newtonsoft NuGet package. I haven't tinkered with anything -- it's all out-of-the-box. – Jacob Stamm Sep 21 '16 at 12:28

2 Answers2

1

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

Strelok
  • 50,229
  • 9
  • 102
  • 115
  • This is perfect! I ended up implementing an even simpler version of this by using `response.Write(JsonConvert.SerializeObject(this.Data))` instead of the `JsonTextWriter` and `JsonSerializer`. I'll never need to use any special `JsonSerializerSettings` or `Formatting`, and working with writers always strikes me as overly complicated. – Jacob Stamm Sep 21 '16 at 18:56
0

Answer is here: How to force ASP.NET Web API to always return JSON?

Excerpt:

Clear all formatters and add Json formatter back.

GlobalConfiguration.Configuration.Formatters.Clear(); GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter()); EDIT

I added it to Global.asax inside Application_Start().

Community
  • 1
  • 1
brandon-barnett
  • 1,035
  • 9
  • 13
  • I am not using Web API. The endpoints on my controller include ViewResults, Json strings, and file results as well, so I don't think this would work for me. – Jacob Stamm Sep 20 '16 at 23:56