"The JSON value could not be converted to Enum in Refit
Asked Answered
A

4

9

I have one .Net Core Razor pages app which is trying to call a .Net Core API with a class library created using Refit.

I have created one Refit API interface which uses a model with enum as one of the property type.

Here is the interface snippet on the API side: IPaymentAPI interface

    [Post("/recharge")]
    Task<string> Recharge([Body] RechargeRequest request);

Here is the request model: The model contains one simple enum ELicenseType.

public class RechargeRequest
{
    public ELicenseType LicenseType{ get; set; }
}

The ELicenseType:

public enum ELicenseType
{
    NotSpecified = 0,
    Standard = 1,
    Commercial = 2
}

The API implementation in controller:

    [HttpPost("recharge")]
    public async Task<IActionResult> Recharge(
        [FromBody] RechargeRequest request)
    {
        Recharge result = await _mediator.Send(_mapper.Map<RechargeCommand>(request));

        return Ok();
    }

When calling this Recharge method the Refit is throwing the ValidationApiException:

ValidationApiException: Response status code does not indicate success: 400 (Bad Request).

And the content is:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-f9178d81421bca438241dd2def43d065-edbd7f210919b24e-00",
  "errors": {
    "$.licenseType": [
      "The JSON value could not be converted to ELicenseType. Path: $.licenseType | LineNumber: 0 | BytePositionInLine: 98."
    ]
  }
}

It seems that the Refit library does not support Enums in the request or my JSON serializer is misconfigured.

Affirm answered 23/8, 2021 at 6:40 Comment(4)
Can you show the enum ELicenseType? Can you show the API action signature?Transpolar
Added the requested code. Please review. FYI the breakpoint on the endpoint is not being hit.Affirm
Return 400 and endpoint not hit... Generally is because the attribute ApiController is somewhere.Transpolar
Maybe this can help you : #68817674Transpolar
L
22

Do you need to set this config in your startup.cs?

 public void ConfigureServices(IServiceCollection services)
 {
     services.AddControllers().AddJsonOptions(opt =>
     {
         opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
     });
 }
Linguini answered 13/11, 2021 at 0:34 Comment(1)
But I don't want to alter the default behavior of my API project, so that it can consume when it is sending int in enum on a container class. How can I send the value which is int instead of enum type name which is string?Largent
S
1

You have to remove Enum JsonStringEnumConverter from serializer settings:

var serializer = SystemTextJsonContentSerializer.GetDefaultJsonSerializerOptions();

serializer.Converters.Remove(serializer.Converters.Single(x => x.GetType().Equals(typeof(JsonStringEnumConverter))));
    var refitSettings = new RefitSettings
    {
        ContentSerializer = new SystemTextJsonContentSerializer(serializer)
    };
services.AddRefitClient<T>(refitSettings)

This helped me. https://github.com/reactiveui/refit/issues/1526

Strander answered 24/5 at 11:8 Comment(0)
D
0

@emielKonig's solution does not work. The one from @artus does in fact work perfectly. I still don't understand how Refit can argue the point that ENUMs should be serialized as a string. No deserializer will recognize this so it just causes issues.

Doran answered 8/8 at 12:11 Comment(0)
H
-1

When creating a Refit implementation for your API's interface, you can provide an instance of RefitSettings.

var refitSettings = new RefitSettings
{
    ContentSerializer = new SystemTextJsonContentSerializer(new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true,
        NumberHandling = JsonNumberHandling.AllowReadingFromString,
        Converters =
        {
            new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
        }
    })
};

var api = RestService.For<IMyApi>(client, refitSettings);

I think that will solve your problem.

Hagiography answered 27/10, 2022 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.