Force lowercase property names from Json() in ASP.NET MVC

asp.net MvcJson

asp.net Mvc Problem Overview


Given the following class,

public class Result
{      
    public bool Success { get; set; }

    public string Message { get; set; }
}

I am returning one of these in a Controller action like so,

return Json(new Result() { Success = true, Message = "test"})

However my client side framework expects these properties to be lowercase success and message. Without actually having to have lowercase property names is that a way to acheive this thought the normal Json function call?

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

The way to achieve this is to implement a custom JsonResult like here: Creating a custom ValueType and Serialising with a custom JsonResult (original link dead).

And use an alternative serialiser such as JSON.NET, which supports this sort of behaviour, e.g.:

Product product = new Product
{
  ExpiryDate = new DateTime(2010, 12, 20, 18, 1, 0, DateTimeKind.Utc),
  Name = "Widget",
  Price = 9.99m,
  Sizes = new[] {"Small", "Medium", "Large"}
};
 
string json = 
  JsonConvert.SerializeObject(
    product,
    Formatting.Indented,
    new JsonSerializerSettings 
    { 
      ContractResolver = new CamelCasePropertyNamesContractResolver() 
    }
);

Results in

{
  "name": "Widget",
  "expiryDate": "\/Date(1292868060000)\/",
  "price": 9.99,
  "sizes": [
    "Small",
    "Medium",
    "Large"
  ]
}

Solution 2 - asp.net Mvc

Changing serializer is simple if you are using Web API, but unfortunately MVC itself uses JavaScriptSerializer with no option to change this to use JSON.Net.

James' answer and Daniel's answer give you the flexibility of JSON.Net but means that everywhere where you would normally do return Json(obj) you have to change to return new JsonNetResult(obj) or similar which if you have a big project could prove a problem, and also isn't very flexible if you change your mind on the serializer you want to use.


I've decided to go down the ActionFilter route. The below code allows you to take any action using JsonResult and simply apply an attribute to it to use JSON.Net (with lower case properties):

[JsonNetFilter]
[HttpPost]
public ActionResult SomeJson()
{
    return Json(new { Hello = "world" });
}

// outputs: { "hello": "world" }

You can even set this up to automagically apply to all actions (with only the minor performance hit of an is check):

FilterConfig.cs

// ...
filters.Add(new JsonNetFilterAttribute());

The code
public class JsonNetFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is JsonResult == false)
            return;

        filterContext.Result = new CustomJsonResult((JsonResult)filterContext.Result);
    }

    private class CustomJsonResult : JsonResult
    {
        public CustomJsonResult(JsonResult jsonResult)
        {
            this.ContentEncoding = jsonResult.ContentEncoding;
            this.ContentType = jsonResult.ContentType;
            this.Data = jsonResult.Data;
            this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
            this.MaxJsonLength = jsonResult.MaxJsonLength;
            this.RecursionLimit = jsonResult.RecursionLimit;
        }

        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("GET not allowed! Change JsonRequestBehavior to AllowGet.");

            var 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)
            {
                var json = JsonConvert.SerializeObject(
                    this.Data,
                    new JsonSerializerSettings
                        {
                            ContractResolver = new CamelCasePropertyNamesContractResolver()
                        });

                response.Write(json);
            }
        }
    }
}

Solution 3 - asp.net Mvc

With my solution, you can rename every property you want.

I've found part of the solution [here][1] and on SO

public class JsonNetResult : ActionResult
    {
        public Encoding ContentEncoding { get; set; }
        public string ContentType { get; set; }
        public object Data { get; set; }

        public JsonSerializerSettings SerializerSettings { get; set; }
        public Formatting Formatting { get; set; }

        public JsonNetResult(object data, Formatting formatting)
            : this(data)
        {
            Formatting = formatting;
        }

        public JsonNetResult(object data):this()
        {
            Data = data;
        }

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

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            var response = context.HttpContext.Response;
            response.ContentType = !string.IsNullOrEmpty(ContentType)
              ? ContentType
              : "application/json";
            if (ContentEncoding != null)
                response.ContentEncoding = ContentEncoding;

            if (Data == null) return;

            var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
            var serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Data);
            writer.Flush();
        }
    }

So that in my controller, I can do that

        return new JsonNetResult(result);

In my model, I can now have:

    [JsonProperty(PropertyName = "n")]
    public string Name { get; set; }

Note that now, you have to set the JsonPropertyAttribute to every property you want to serialize. [1]: http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net

Solution 4 - asp.net Mvc

Though it is an old question, hope below code snippet will be helpful to others,

I did below with MVC5 Web API.

public JsonResult<Response> Post(Request request)
    {
        var response = new Response();
        
        //YOUR LOGIC IN THE METHOD
        //.......
        //.......

        return Json<Response>(response, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() });
    }

Solution 5 - asp.net Mvc

You can add this setting to Global.asax, and it will work everywhere.

public class Global : HttpApplication
{	
    void Application_Start(object sender, EventArgs e)
    {
		//....
         JsonConvert.DefaultSettings = () =>
		 {
			 var settings = new JsonSerializerSettings
			 {
				 ContractResolver = new CamelCasePropertyNamesContractResolver(),
				 PreserveReferencesHandling = PreserveReferencesHandling.None,
				 Formatting = Formatting.None
			 };

			 return settings;
		 }; 
         //....
	 }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames HughesView Question on Stackoverflow
Solution 1 - asp.net MvcJames HughesView Answer on Stackoverflow
Solution 2 - asp.net Mvcdav_iView Answer on Stackoverflow
Solution 3 - asp.net MvcDanielView Answer on Stackoverflow
Solution 4 - asp.net MvcpgcanView Answer on Stackoverflow
Solution 5 - asp.net MvcMaksym LabutinView Answer on Stackoverflow