12

I'm trying to return camel cased JSON from an ASP.Net Web API 2 controller. I created a new web application with just the ASP.Net MVC and Web API bits in it. I hijacked the ValuesController like so:

public class ValuesController : ApiController
{
    public class Thing
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string ISBN { get; set; }
        public DateTime ReleaseDate { get; set; }

        public string[] Tags { get; set; }
    }

    // GET api/values
    public IHttpActionResult Get()
    {
        var thing = new Thing
        {
            Id = 123,
            FirstName = "Brian",
            ISBN = "ABC213", 
            ReleaseDate = DateTime.Now,
            Tags = new string[] { "A", "B", "C", "D"}
        };

        return Json(thing);
    }
}

Running this in IE, I get the following results:

{"Id":123,"FirstName":"Brian","ISBN":"ABC213","ReleaseDate":"2014-10-20T16:26:33.6810554-04:00","Tags":["A","B","C","D"]}

Following K. Scott Allen's post on the subject, I added the following to the Register method in the WebApiConfig.cs file:

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        var formatters = GlobalConfiguration.Configuration.Formatters;
        var jsonFormatter = formatters.JsonFormatter;
        var settings = jsonFormatter.SerializerSettings;
        settings.Formatting = Formatting.Indented;
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

However, I still get the same, capitilization in my results. Is there something I'm missing? I've tried a few other approaches but nothing works yet.

beaudetious
  • 2,354
  • 3
  • 36
  • 60
  • Is this such an obvious answer that people think I should figure this out myself? I haven't got a nibble yet. I started with a new project and was still not able to get this working. – beaudetious Oct 21 '14 at 16:33
  • I still think answer from another post is the most decent one: http://stackoverflow.com/a/22130487/1915401 – Xinan Jan 02 '16 at 02:47

6 Answers6

15

In your WebApiConfig.cs make sure to add those two lines

// Serialize with camelCase formatter for JSON.
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

make sure that you installed Newtonsoft library.

Hope that helps.

Omar.Alani
  • 4,050
  • 2
  • 20
  • 31
9

Looks like the main issue was that I was using the JsonResult shortcut Json() action result method:

public IHttpActionResult Get([FromUri] string domain, [FromUri] string username)
{
    var authInfo = BLL.GetAuthenticationInfo(domain, username);
    return Json(authInfo);
}

It apparently had full control of formatting the results. If I switch to returning HttpResponseMessage then it works as expected:

public HttpResponseMessage Get([FromUri] string domain, [FromUri] string username)
{
    var authInfo = BLL.GetAuthenticationInfo(domain, username);
    return Request.CreateResponse(HttpStatusCode.OK, authInfo);
}

I did end up using the block of code in the WebApiConfig file as Omar.Alani suggested (opposed to the much lengthier code I had in my OP). But the real culprit was the JsonResult action method. I hope this helps someone else out.

beaudetious
  • 2,354
  • 3
  • 36
  • 60
  • 6
    I know this is a rather late comment but I found that using `Ok(authInfo)` applies the formatter whereas using `Json(authInfo)` does not. The `Ok` method would apply the relevant formatter based on the `Accept` header. You could then still return `IHttpActionResult`. – Eben Roux Dec 27 '15 at 08:22
5

You need to use OK() instead of Json() in your action methods.

// GET api/values
public IHttpActionResult Get()
{
    var thing = new Thing
    {
        Id = 123,
        FirstName = "Brian",
        ISBN = "ABC213", 
        ReleaseDate = DateTime.Now,
        Tags = new string[] { "A", "B", "C", "D"}
    };

    // Use 'Ok()' instead of 'Json()'
    return Ok(thing);
}
Jalal
  • 6,594
  • 9
  • 63
  • 100
3

In Register method of WebApiConfig, add this

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

Full Code of WebApiConfig:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

        }
    }


Make sure you have installed latest version of Json.Net/Newtonsoft.Json Installed and your API Action Method returns data in following way:

    [HttpGet]
    public HttpResponseMessage List()
    {
        try
        {
            var result = /*write code to fetch your result*/;
            return Request.CreateResponse(HttpStatusCode.OK, result);
        }
        catch (Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
        }
    }
Jay Shah
  • 3,553
  • 1
  • 27
  • 26
1

I was using Owin and DI (AutoFac in my case) so that throws another wrench into the works. My Startup.cs contains:

var apiconfig = new HttpConfiguration
{
    DependencyResolver = new AutofacWebApiDependencyResolver(container)
};
WebApiConfig.Register(apiconfig);

Then in my WebApiConfig.cs I have:

using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        //  Setup json.Net for pretty output, easy human reading AND this formatter
        //  does that ONLY for browsers - best of both worlds: useful AND efficient/performant!
        config.Formatters.Clear();
        config.Formatters.Add(new BrowserJsonFormatter());
    }

    public class BrowserJsonFormatter : JsonMediaTypeFormatter
    {
        //  Since most browser defaults do not include an "accept type" specifying json, this provides a work around
        //  Default to json over XML - any app that wants XML can ask specifically for it  ;)
        public BrowserJsonFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
            SerializerSettings.Formatting = Formatting.Indented;
            SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            // Convert all dates to UTC
            SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
        }

        //  Change the return type to json, as most browsers will format correctly with type as text/html
        public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
        {
            base.SetDefaultContentHeaders(type, headers, mediaType);
            headers.ContentType = new MediaTypeHeaderValue("application/json");
        }
    }
Jester
  • 2,728
  • 22
  • 20
0

Try this also.

[AllowAnonymous]
[HttpGet()]
public HttpResponseMessage GetAllItems(int moduleId)
{
            HttpConfiguration config = new HttpConfiguration();
            config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;

            try
            {
                List<ItemInfo> itemList = GetItemsFromDatabase(moduleId);
                return Request.CreateResponse(HttpStatusCode.OK, itemList, config);
            }
            catch (System.Exception ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
            }
}
Khademul Basher
  • 127
  • 1
  • 2