For a polymorphic Web API endpoint. Is there a way to configure the type discriminator?
I only found a solution with a JsonConverter. But the problem is the framework behaves then a bit different. E.g. the ValidationAttributes do not get evaluated any more.
Also the code feels like somehow "bypassing" the framework
[JsonConverter(typeof(ScheduleApiConverter))]
public class ScheduleBase
{
public string Type { get; set; }
// [...]
}
public class ScheduleApiConverter : ApiTypeConverter<ScheduleBase> { protected override ScheduleBase Create(Type objectType, JObject jObject) { // TODO: read the raw JSON object through jObject to identify the type // e.g. here I'm reading a 'typename' property: var typeString = jObject.Value<string>("Type"); if (ScheduleMongoConverter.WEEKLY_DISCRIMINATOR.Equals(typeString)) { return new ScheduleWeekly(); } else if (ScheduleMongoConverter.DAILY_DISCRIMINATOR.Equals(typeString)) { return new ScheduleDaily(); } else if (ScheduleMongoConverter.ONCE_DISCRIMINATOR.Equals(typeString)) { return new ScheduleOnce(); } else { return new ScheduleOnce(); } //now the base class' code will populate the returned object. } } public abstract class ApiTypeConverter<T> : JsonConverter { // List<string> Errors = new List<string>(); // this is very important, otherwise serialization breaks! public override bool CanWrite { get { return false; } } // Create an instance of objectType, based properties in the JSON object // objectType: type of object expected // jObject: contents of JSON object that will be deserialized protected abstract T Create(Type objectType, JObject jObject); public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; // Load JObject from stream JObject jObject = JObject.Load(reader); // Create target object based on JObject T target = Create(objectType, jObject); // Populate the object properties serializer.Populate(jObject.CreateReader(), target); return target; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }