Search code examples
enumsintegerasp.net-core-3.1model-binding

ASP.NET core JSON model binding int to enum


Scenario

I want to map an incoming JSON request which has integer values to corresponding Enum values. The code below is simplified for the question in reality there are much more fields on MyRequest class.

Data Code


public enum Policy
{
    Unknown = 0,
    Policy1 = 1,
    Anticipated = 2
}

public enum Design
{
    Unknown = 0,
    Project = 1,
    Days = 2
}

public class Policies
{
    public Policy? PolicyId { get; set; } 

    public Design? DesignId { get; set; } 
}

class MyRequest
{
    public int Id { get; set; }

    public Policies Policies { get; set; }
}

JSON Request

{
    "policies": {
        "policyId": 2,
        "designId": 2
    },
    "id": 1
}

Controller Code

[HttpPut]
public async Task<IActionResult> Put(MyRequest request)
{
    // reques.Policies.DesignId is null
    // reques.Policies.PolicyId is null
}

Solution

  • After digging deeper into the problem and with almost no docs by Microsoft I found this similar question that gave me the right direction: implement a custom JSONConverter.

    JSONConverter

    public class ContractConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(Policies) == objectType;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var rawValue = serializer.Deserialize<dynamic>(reader);
            var policyId = (Policy)(rawValue.policyId);
            var designId = (Design)(rawValue.designId);
            return new Policies(policyId, designId);
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override bool CanWrite => false;
    }
    

    Startup.cs

     services.AddControllers()
                    .AddNewtonsoftJson(o=> o.SerializerSettings.Converters.Add(new ContractConverter()));