12

I've used WebAPI for a while, and generally set it to use camel case json serialization, which is now rather common and well documented everywhere.

Recently however, working on a much larger project, I came across a more specific requirement: we need to use camel case json serialization, but because of backward compatibility issues with our client scripts, I only want it to happen for specific actions, to avoid breaking other parts of the (extremely large) website.

I figure one option is to have a custom content type, but that then requires client code to specify it.

Is there any other option?

Thanks!

Francois Ward
  • 123
  • 1
  • 5

1 Answers1

30

Try this:

public class CamelCasingFilterAttribute : ActionFilterAttribute
{
    private JsonMediaTypeFormatter _camelCasingFormatter = new JsonMediaTypeFormatter();

    public CamelCasingFilterAttribute()
    {
        _camelCasingFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
        if (content != null)
        {
            if (content.Formatter is JsonMediaTypeFormatter)
            {
                actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, _camelCasingFormatter);
            }
        }
    }
}

Apply this [CamelCasingFilter] attribute to any action you want to camel-case. It will take any JSON response you were about to send back and convert it to use camel casing for the property names instead.

mare
  • 13,033
  • 24
  • 102
  • 191
Youssef Moussaoui
  • 12,187
  • 2
  • 41
  • 37
  • Note that this solution does not work when using WebAPI OData and actions that return SingleResult. You need to change the innermost line where it sets the Content property to be this instead: var newContent = new ObjectContent(content.ObjectType, null, _camelCasingFormatter); newContent.Value = content.Value; actionExecutedContext.Response.Content = newContent; – Paul Dec 04 '14 at 22:42
  • Is there a way to do this in reverse, i.e. you have CamelCase by default, but on an action, add a "NoCasingFilter" attribute? – Sean Feb 26 '15 at 12:01
  • 2
    Got it: `JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();` – Sean Feb 26 '15 at 12:21
  • Thanks for the reverse one as well! This makes sure new actions by default are camelCased :-) – Zenuka Mar 24 '15 at 12:41
  • 1
    Be *really* careful using this with an IoC container (e.g. Ninject, SimpleInjector etc) that bootstraps all your API controllers by default. I just spent ages trying to figure out why controllers I hadn't added this attribute to were being camel cased. Basically, all my controller were being created by default and this attribute modifies the global serialiser settings so that was propagating across every controller. – GFoley83 Oct 30 '15 at 01:48
  • amazing save my day to reverse general camel case resolver using @Sean answer – Hisham Feb 25 '16 at 11:48
  • @GFoley83 that only happens because this code is setting static version of JsonMediaTypeFormatter which of course creates only one instance and that then propagates all over the place. The author of this answer should change it to use private instance. – mare Aug 19 '16 at 08:42
  • @mare Yes I know that now but I had to find that out the hard way. – GFoley83 Aug 19 '16 at 08:48