Problem


Azure Function Isolated worker for .NET replaced its default Json Serializer from Newtonsoft.Json with System.Text.Json. This change caused certain behavior differences. In my case, I am not able to deserialize an Enum type from a string value. 

My request object is EventLogQueryRequest

public class EventLogQueryRequest
{
    public int Take { get; set; } = 100;

    public MpsEventId[] EventIds { get; set; }

    public Guid? UserId { get; set; }
}

MpsEventId is a C# enum type.

public enum MpsEventId
{
    General = 0,

    Login = 1001,
    Logout = 1002
    // ...
}

When client send request that uses string value for the Enum, an exception will be thrown.

{
    "take": 10,
    "eventIds": [
        "Login",
        "CreateEditCard",
        "SubmitReviewCard"
    ],
    "userId": null
}
Exception: System.InvalidOperationException: The JSON value could not be converted to MPSFunc.EventLog.MpsEventId. Path: $.eventIds[0] | LineNumber: 3 | BytePositionInLine: 15.

Solution


At first, among my search from the Internet, I can Configure JsonSerializerOptions in Program.cs in this way. But unfortunately, this won't work.

services.Configure<JsonSerializerOptions>(options =>
{
    options.PropertyNameCaseInsensitive = true;
    options.Converters.Add(new JsonStringEnumConverter())
});

The correct way is to use AddJsonOptions() method just like a normal ASP.NET Core application.

services.AddControllers()
        .AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

The complete Program.cs now looks like this:

using System.Text.Json.Serialization;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddControllers()
                .AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));

        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

Now, the request can be successfully serialized, the code works like a charm!