'Unable to Deserialize Json in WebApi with JsonSubTypes in .NET 5, although able to in Console App

I am trying to implement polymorphic deserialization in my project's web api. I have the following base and derived class.

Base class

    [JsonConverter(typeof(JsonSubtypes), "PointType")]
    public abstract class BasePointRule
    {
       public abstract string PointType { get; }
    }

Derived Class

    public class DayOfWeekPointRule : BasePointRule
{
    public int Id { get; set; }
    public decimal Mon { get; set; } = 0;
    public decimal Tue { get; set; } = 0;
    public decimal Wed { get; set; } = 0;
    public decimal Thu { get; set; } = 0;
    public decimal Fri { get; set; } = 0;
    public decimal Sat { get; set; } = 0;
    public decimal Sun { get; set; } = 0;
    public int GroupId { get; set; }
    public Group Group { get; set; }
    public override string PointType { get;} = "DayOfWeekPointRule";


    public DayOfWeekPointRule()
    {
    }
}

I get an error when posting the json for the child type to my Web Api controller. Here is the json with double quotes escaped:

{
    "PointType":"DayOfWeekPointRule",
    "Mon":0,
    "Tue":0,
    "Wed":0,
    "Thu":0,
    "Fri":0,
    "Sat":0,
    "Sun":0
}

Here is the web api controller method:

        [HttpPost("AddPointRule")]
    public IActionResult AddPointRule(BasePointRule rule)
    {

        ConfigurationService.AddPointRule(rule);
        return Ok();
    }

The error message I get is:

System.InvalidOperationException: Could not create an instance of type 'RosterCharm.Models.Rules.BasePointRule'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'rule' parameter a non-null default value. at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.CreateModel(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext, Int32 propertyData) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container) at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext() --- End of stack trace from previous location ---

If I change the parameter in the controller route from the base class to the derived class, the json is deserialized correctly.

If I implement the above in a console application and call the following then the json is deserialized to the derived type without issue as well:

var derivedType = JsonConvert.DeserializeObject<BasePointRule>(json);

This led me to think that the issue is specific to .Net (I am using .Net 5), and have tried ensuring I am using Json.NET (Newtonsoft.Json, I think) instead of System.Text.Json by calling the following in my startup.cs

services.AddControllers().AddNewtonsoftJson();

Any tips would be much appreciated. Am thinking to try implementing my own Json converter next but was hoping to be able to leverage the json subtypes library for ease.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source