我在ASP.NET Web API项目中使用实体框架代码优先table-per-hierarchy。我的一个模型有一个List,它是层次结构的抽象基类的类型。
List<Dog> // (for example; with GoldenRetriever, BorderCollie, etc inheriting)
我正在尝试使用Fiddler测试将一些数据发布到我的API控制器。但是当我这样做时,我不知道如何表示JSON。如果我尝试这样的话:
"Dogs":
[
{"Name":"Bud", "Age":"3"}
]
我收到错误:
“无法创建Models.Dog类型的实例.Type是一个接口 或抽象类,无法实例化。“
在JSON中指定Discriminator对我也没有帮助。有人有主意吗?谢谢!
编辑:解决方案
诀窍是在JSON字符串中使用$ type属性。有关更多信息,请参阅评论中m.t.bennett建议的this link。
要启用$ type属性,我需要将以下内容添加到WebApiConfig.cs中:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling
= TypeNameHandling.Auto;
然后在将JSON发布到Fiddler时,我添加了带有完整对象路径的$ type属性:
{"$type":"Example.Models.Dogs.GoldenRetriever, Example.Models",
"Name":"Bud","Age":3}
为了弄清楚这种格式,我使用了Snixtor的建议来序列化一个对象并输出JSON字符串。辉煌!
我不确定这是否是最优雅的解决方案,因为它是JSON.NET specific,但它有效!
答案 0 :(得分:0)
我使用自定义JsonConverter来处理基类型反序列化。
public override bool CanConvert(Type objectType) {
return typeof(Mybase).Equals(objectType);
}
public override MyBase Deserialize(JsonReader reader, MyBase existingValue, JsonSerializer serializer) {
var ret = existingValue;
var jobj = JObject.ReadFrom(reader);
if (jobj["type"] == null || jobj["type"].Type != JTokenType.String)
throw new JsonSerializationException("Supplied JSON is missing the required 'type' member.");
var typeName = jobj["type"].Value<string>();
var t = this.GetType().Assembly.GetType("MyNamespace." + typeName);
if(t == null)
throw new JsonSerializationException(String.Format("Could not identify supplied type '{0}' as a known type.", typeName));
if (existingValue != null && !t.IsInstanceOfType(existingValue))
throw new JsonSerializationException(String.Format("Type Mismatch: existingValue {0} is not assignable from supplied Type {1}", existingValue.GetType().Name, t.Name));
ret = (ContactMethod)jobj.ToObject(t);
return ret;
}
在应用程序初始化期间注册了JsonConverter:
JsonSerializerSettings settings;
settings.Converters.Add(new MyBaseConverter());