I have scaffolded an Azure Functions application using .NET 9. The Program.cs
file looks like this:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = FunctionsApplication.CreateBuilder(args);
builder.ConfigureFunctionsWebApplication();
builder.Services
.AddApplicationInsightsTelemetryWorkerService()
.ConfigureFunctionsApplicationInsights();
builder.Build().Run();
Inspecting the code reveals ConfigureFunctionsWebApplication
calls Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.AddFunctionsWorkerDefaults
which configures default JSON serialisation to ignore property name case.
This is not the behaviour I am experiencing. My endpoint is configured to accept the following JSON body:
{
"Double": 2
}
If the parameter name is lowercase, the JSON deserialization fails and the value is defaulted to zero.
I found this post suggesting either Microsoft.AspNetCore.Http.Json.JsonOptions
or Microsoft.AspNetCore.Mvc.JsonOptions
needs to be configured. I don't believe this should be necessary and neither option worked for me anyway. .NET 8 Azure Functions: setting System.Text.JsonSerializer defaults
Any suggestions? I have committed sample code here https://github.com/DangerousDarlow/AzureFunctionsExplore
The function code is https://github.com/DangerousDarlow/AzureFunctionsExplore/blob/master/AzureFunctionsExplore/Math.cs
public class Math(ILogger<Math> logger)
{
[Function("Double")]
[OpenApiOperation("Double")]
[OpenApiRequestBody("application/json", typeof(Body), Required = true)]
[OpenApiResponseWithBody(HttpStatusCode.OK, "'application/json'", typeof(Body))]
public async Task<IActionResult> Double([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest request)
{
var requestBodyString = await new StreamReader(request.Body).ReadToEndAsync();
var requestBody = JsonSerializer.Deserialize<Body>(requestBodyString);
logger.LogInformation("Doubling number: {number}", requestBody?.Double);
return new OkObjectResult(new Body (requestBody?.Double * 2 ?? 0 ));
}
public record Body(int Double);
}
After further investigation I have concluded that function ConfigureFunctionsWebApplication does initialise JSON serialization with sensible options including case insensitive parameter names however I was not using these options with the serializer in my endpoint implementation. I needed to inject them into the class implementing the endpoint and pass them to the serializer.
public class Math(IOptions<JsonSerializerOptions> jsonSerializerOptions, ILogger<Math> logger)
{
private readonly JsonSerializerOptions _jsonSerializerOptions = jsonSerializerOptions.Value;
[Function("Double")]
[OpenApiOperation("Double")]
[OpenApiRequestBody("application/json", typeof(Body), Required = true)]
[OpenApiResponseWithBody(HttpStatusCode.OK, "'application/json'", typeof(Body))]
public async Task<IActionResult> Double([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest request)
{
var requestBodyString = await new StreamReader(request.Body).ReadToEndAsync();
var requestBody = JsonSerializer.Deserialize<Body>(requestBodyString, _jsonSerializerOptions);
logger.LogInformation("Doubling number: {number}", requestBody?.Double);
return new OkObjectResult(new Body (requestBody?.Double * 2 ?? 0 ));
}
public record Body(int Double);
}
It may also be possible to configure the default options used by the static JsonSerializer instance however I haven't explored this further as injecting the options suits my purpose and it's clear.