Search code examples
c#asp.net-corejson-deserializationmicrosoft-graph-sdks

ASP.NET model binding fails for enums with MSGraphSDK v5


Someone needs to send a JSON file to my ASP.NET webapp, representing a Microsoft.Graph.Beta.Models.ImportedDeviceIdentity.

Here is my controller action:

 [Consumes("application/json")]
 public IActionResult HandleImportDeviceIdentity([FromBody] Microsoft.Graph.Beta.Models.ImportedDeviceIdentity importDeviceIdentity)
 {
     ...
     return Ok();
 }

I am using MSGraphSDKDotNet v5 with ASP.NET (.NET Core 7).

If I send a JSON file like this:

    {
        "importedDeviceIdentityType": "serialNumber",
        "importedDeviceIdentifier": "TEST9999",
        "description": "TEST999"
    }

...then my importDeviceIdentity object is not properly initialized (it is set to null).

But if I use the numeric value for the importedDeviceIdentityType Enum like:

    {
        "importedDeviceIdentityType": 2,
        "importedDeviceIdentifier": "TEST9999",
        "description": "TEST999"
    }

...all is working fine.

I wasn't able to understand why ASP.Net was unable to bind the Enum string representation to the integer value, even if the ImportedDeviceIdentity object inherits from IParsable.

I don't won't to write a custom JSON converter, nor I would like to use cheap solution, such as binding to a string and de-serializing using the object methods (CreateFromDiscriminatorValue and Co...)

Seems I lack something like [JsonConverter(typeof(JsonStringEnumConverter))] on the Enum, but as the class was not defined by myself, I cannot do that. There is also no "@odata.type" attribute on the payload my controller will receive (not sure if this is relevant).

How can I convert the string representation properly during the model binding step?


Solution

  • By default, enums are serialized as numbers. To serialize enum names as strings, use the JsonStringEnumConverter.

    Globally register it in Program.cs like below:

    builder.Services.AddControllersWithViews().AddJsonOptions(opts =>
    {
        var enumConverter = new JsonStringEnumConverter();
        opts.JsonSerializerOptions.Converters.Add(enumConverter);
    });