I am trying to deserialize a subclass in a .NET 5 api project. The model binder is handing back a null even though my custom JSON converter is being called and is returning the correct object.
So that I can have polymorphic deserialization, I'm using the NewtonSoft serializer, added like so:
services
.AddControllers()
.AddNewtonsoftJson(opts =>
{
opts.SerializerSettings.Converters.Insert(0, new RecordJsonConverter());
});
And I have Microsoft.AspNetCore.Mvc.NewtonsoftJson added to the project.
The classes are like:
public class RecordDTO
{
[...]
}
public class ARecordDTO : RecordDTO
{
[...]
}
The controller accepts the base class:
public async override Task<IActionResult> Post([FromBody] RecordDTO dto)
And the JSON Converter:
public class RecordJsonConverter : JsonConverter
{
public override bool CanWrite
{
get
{
return false;
}
}
public override bool CanRead
{
get
{
return true;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
// Only objects of the base type RecordDTO need to be converted by this custom converter.
// If it is already knows which derived class it is, then we
// can just let it use the standard converter.
var recordType = typeof(RecordDTO);
return recordType.IsAssignableFrom(objectType) && !objectType.IsSubclassOf(recordType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
[...]
return target;
}
}
When I post an ARecordDTO object, I see ReadJson on my custom RecordJsonConverter being called and filling out an ARecord object and returning it correctly.
But then we're back inside the controller action, and the dto argument is now null instead of being the ARecordDTO that was just created for binding.
Has anyone else encountered this? What would cause the object returned by the JSON converter to be discarded during binding?