5

We are trying to migrate an old API into our current .Net Core Web API. Our current API returns JSON using camelCasing, but our old API uses PascalCasing and we do not want to have to update the client.

Is there any way to specify which serialization strategy we want to use per controller, rather than global across the service?

Zachary Wand
  • 346
  • 4
  • 11
  • Possible duplicate of [asp.net core 1.0 web api use camelcase](http://stackoverflow.com/questions/38139607/asp-net-core-1-0-web-api-use-camelcase) – Set Apr 20 '17 at 06:36
  • I don't think so, I believe that is just asking for camelCase across the entire API, not per controller – Zachary Wand Apr 20 '17 at 14:19
  • We ended up adding [JsonProperty] tags to every attribute in our relevant models. Not the ideal solution (we have LOTS of models) but it is working for now. – Zachary Wand Apr 25 '17 at 14:27

2 Answers2

8

Yes, you can achieve it by using attribute on your controller. See the sample below:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomJsonFormatter : ActionFilterAttribute
{
    private readonly string formatName = string.Empty;
    public CustomJsonFormatter(string _formatName)
    {
        formatName = _formatName;
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        if (context == null || context.Result == null)
        {
            return;
        }

        var settings = JsonSerializerSettingsProvider.CreateSerializerSettings();

        if (formatName == "camel")
        {
            settings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
        }            
        else
        {
            settings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
        }

        var formatter = new JsonOutputFormatter(settings, ArrayPool<Char>.Shared);

        (context.Result as Microsoft.AspNetCore.Mvc.OkObjectResult).Formatters.Add(formatter);
    }
}

and here is your controller:

[CustomJsonFormatter("camel")]
[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET: api/values
    [HttpGet]
    public IActionResult Get()
    {
        Car car = new Car { Color = "red", Make = "Nissan" };

        return Ok(car);
    }        
}
armache
  • 596
  • 5
  • 22
  • Thanks @armache but I found my results were JsonResult not OKObjectResult so instead I had `((Microsoft.AspNetCore.Mvc.JsonResult)context.Result).SerializerSettings = settings;` Also note that DefaultContractResolver isn't strictly PascalCase as the OP specified, it doesn't modify the case, normally C# will already be PascalCase and so it will stay PascalCase; it's probably what they wanted rather than what they asked for. I also removed the parameter from the attribute as it defaults to camel case and so only specify the attribute if I need PascalCase. – Mog0 May 17 '18 at 16:59
1

I have made an extension method for OkObjectResult to be able to choose where I do not want the camel case serialization behaviour. You can use it like this:

OkObjectResult(yourResponseObject).PreventCamelCase();

Here is the extension method:

public static OkObjectResult PreventCamelCase(this OkObjectResult response)
{
    var settings = JsonSerializerSettingsProvider.CreateSerializerSettings();
    settings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();

    var formatter = new JsonOutputFormatter(settings, ArrayPool<Char>.Shared);
    response.Formatters.Add(formatter);
    return response;
}
Danie
  • 429
  • 6
  • 16
  • @GabrielLuca I also wonder that. I have been using this solution for half a year now in my 100+ API endpoints without any problems. Saved me probably at least one week of work not having to rewrite the clients after updating the API to .NET Core. This solution also let me choose which endpoints where I want this behaviour and not, so I can slowly transition my whole API to the new standards of .NET Core. – Danie Feb 22 '20 at 17:33