Search code examples
c#azure.net-corejson.netazure-functions

C# Set Casing Convention Globally for Azure Function v3


I am new to Azure Functions and trying to convert .NET Core APIs to Azure Functions. The problem I am facing is how to globally set response naming convention (JSON). By default, it is CamelCase but I want to use PascalCase, all the solutions I found on internet were to modify the response in each function / endpoint. I would like to set it up globally

I had already added Startup.cs to configure DIs. Here is what I have tried in attempt to configure response JSON naming convention:

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddMvcCore().AddJsonOptions(m =>
    {
        m.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

    builder.Services.Configure<JsonSerializerSettings>(m =>
    {
        m.ContractResolver = new DefaultContractResolver();
    });

    builder.Services.Configure<JsonSerializerOptions>(m =>
    {
        m.DictionaryKeyPolicy = null;
        m.PropertyNamingPolicy = null;
    });

    builder.Services.Configure<JsonOptions>(m =>
    {
        m.JsonSerializerOptions.DictionaryKeyPolicy = null;
        m.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

    .....
}

Function Example (both return same response, which is CamelCased):

[FunctionName(nameof(Get))]
public async Task<IEnumerable<AppComponentViewModel>> Get([HttpTrigger(AuthorizationLevel.Function, "get", Route = "AppComponent/Get")] HttpRequest request)
{
    var appComponents = await _appComponentRepository.GetAll();
    return ToList(appComponents);
}

[FunctionName(nameof(Get))]
public async Task<ActionResult<IEnumerable<AppComponentViewModel>>> Get([HttpTrigger(AuthorizationLevel.Function, "get", Route = "AppComponent/Get")] HttpRequest request)
{
    var appComponents = await _appComponentRepository.GetAll();
    return Ok(ToList(appComponents));
}

Solution

  • By default, Azure function host uses 'Newtonsoft.Json' as opposed to 'System.Text,Json' introduced in .net core 3+. You can use the below code in Startup.cs to override MVC Json serialization behavior which would retain your property name casing same as in your entity classes. In the below code it will not convert to camelCase anymore, but at the same time would neither explicitly convert to PascalCase. It would be same as the C# object.

    NOTE: Add nuget Microsoft.AspNetCore.Mvc.NewtonsoftJson version 3.1.* ( not newest 5 at least until Function start supporting .net 5).

            public override void Configure(IFunctionsHostBuilder builder)
            {
                builder.Services.AddMvc()
                    .AddNewtonsoftJson(o =>
                    {
                        o.SerializerSettings.ContractResolver = new DefaultContractResolver();
                    });
            }
    

    If you want to specifically force to Pascal case for everything regardless of what is the casing in C# object, then you can create your NamingStrategy class to have that logic and assign it.

        public class MyNamingStrategy : NamingStrategy
        {
            protected override string ResolvePropertyName(string s)
            {
                // add logic to force name to desired casing
            }
        }    
    
            public override void Configure(IFunctionsHostBuilder builder)
            {
                builder.Services.AddMvc()
                    .AddNewtonsoftJson(o =>
                    {
                        o.SerializerSettings.ContractResolver = new DefaultContractResolver
                        {
                            NamingStrategy = new MyNamingStrategy()
                        };
                    });
            }