Enum type no longer working in .Net core 3.0 FromBody request object
Asked Answered
W

3

36

I have recently upgraded my web api from .Net core 2.2 to .Net core 3.0 and noticed that my requests are getting an error now when I pass an enum in a post to my endpoint. For example:

I have the following model for my api endpoint:

public class SendFeedbackRequest
{
    public FeedbackType Type { get; set; }
    public string Message { get; set; }
}

Where the FeedbackType looks like so:

public enum FeedbackType
{
    Comment,
    Question
}

And this is the controller method:

[HttpPost]
public async Task<IActionResult> SendFeedbackAsync([FromBody]SendFeedbackRequest request)
{
    var response = await _feedbackService.SendFeedbackAsync(request);

    return Ok(response);
}

Where I send this as the post body to the controller:

{
    message: "Test"
    type: "comment"
}

And I am now getting the following error posting to this endpoint:

The JSON value could not be converted to MyApp.Feedback.Enums.FeedbackType. Path: $.type | LineNumber: 0 | BytePositionInLine: 13."

This was working in 2.2 and started the error in 3.0. I saw talk about the json serializer changing in 3.0, but not sure how this should be handled.

Woodworm answered 17/10, 2019 at 20:37 Comment(0)
M
35

As of version 3.0, .NET Core no longer uses the third-party Newtonsoft.Json (Json.NET) by default but the new, built-in System.Text.Json (STJ) serializer - which is not as feature-rich as Json.NET, and of course has its own issues and learning curve to get the expected features.

If you’d like to switch back to the previous default of using Newtonsoft.Json, then you'll have to do the following:

  1. Install the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

  2. In ConfigureServices() add a call to AddNewtonsoftJson()

public void ConfigureServices(IServiceCollection services) {
    //...

    services.AddControllers()
        .AddNewtonsoftJson(); //<--

    //...
}
Monney answered 17/10, 2019 at 20:49 Comment(1)
I'd like to point out both steps have to be taken. Which is quite obvious, but if you forget the Nuget package and only add "AddNewtonsoftJson()" then your code compiles and runs just fine, while it doesn't work.Prostitution
G
69

For those who are looking for a snippet when using System.Text.Json

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddJsonOptions(opt =>
    {
        opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    });
}

.NET 6 / Top-level statement style

using System.Text.Json.Serialization;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers()
    //convert strings to enums
    .AddJsonOptions(options =>
        options.JsonSerializerOptions.Converters
            .Add(new JsonStringEnumConverter()));
Gynandry answered 24/10, 2019 at 8:57 Comment(3)
It should be StringEnumConverter, not JsonStringEnumConverter.Dehydrogenase
@Dehydrogenase JsonStringEnumConverter is correct unless you use json from newtonsoft but then also JsonSerializerSettings should be used and not JsonSerializerOptions.Hereat
Another thing that used to work out of the box but now doesn'tProve
M
35

As of version 3.0, .NET Core no longer uses the third-party Newtonsoft.Json (Json.NET) by default but the new, built-in System.Text.Json (STJ) serializer - which is not as feature-rich as Json.NET, and of course has its own issues and learning curve to get the expected features.

If you’d like to switch back to the previous default of using Newtonsoft.Json, then you'll have to do the following:

  1. Install the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

  2. In ConfigureServices() add a call to AddNewtonsoftJson()

public void ConfigureServices(IServiceCollection services) {
    //...

    services.AddControllers()
        .AddNewtonsoftJson(); //<--

    //...
}
Monney answered 17/10, 2019 at 20:49 Comment(1)
I'd like to point out both steps have to be taken. Which is quite obvious, but if you forget the Nuget package and only add "AddNewtonsoftJson()" then your code compiles and runs just fine, while it doesn't work.Prostitution
Q
8

Support for serializing enums as strings already exist if you use the built-in JsonStringEnumConverter and pass that into the JsonSerializerOptions: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonstringenumconverter?view=netcore-3.0

Here's a sample test that uses it: https://github.com/dotnet/corefx/blob/master/src/System.Text.Json/tests/Serialization/ReadScenarioTests.cs#L17

Quanta answered 17/10, 2019 at 20:49 Comment(1)
For those who do not know how to pass JsonStringEnumConverter into the JsonSerialzerOptions, here are the code: services.AddMvc() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.IgnoreNullValues = true; });Hileman

© 2022 - 2024 — McMap. All rights reserved.