8

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.

Kishan Vaishnav
  • 2,273
  • 1
  • 17
  • 45
  • 1
    Can you show the enum `ELicenseType`? Can you show the API action signature? – vernou Aug 23 '21 at 07:02
  • Added the requested code. Please review. FYI the breakpoint on the endpoint is not being hit. – Kishan Vaishnav Aug 23 '21 at 07:25
  • Return 400 and endpoint not hit... Generally is because the attribute [ApiController](https://learn.microsoft.com/en-us/aspnet/core/web-api#automatic-http-400-responses) is somewhere. – vernou Aug 23 '21 at 08:19
  • Maybe this can help you : https://stackoverflow.com/questions/68817174/api-request-is-null-when-using-sendasync/68819048#68819048 – vernou Aug 23 '21 at 08:21

2 Answers2

20

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());
     });
 }
karel
  • 5,489
  • 46
  • 45
  • 50
yuriDuque
  • 201
  • 2
  • 3
  • 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? – Abdullah Rana Jul 07 '22 at 11:06
0

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.

Emiel Koning
  • 4,039
  • 1
  • 16
  • 18