获取JSON序列化实体框架自我引用即使在ProxyCreation之后循环错误,当使用显式包含时为false [英] Getting JSON Serialization Entity Framework Self Reference Loop error even after ProxyCreation false when using explicit Include
问题描述
JSON序列化(ASP.Net Web API)因为自引用循环而失败(这是一个常见的问题,原因是:被请求的实体懒惰加载子实体,每个子项都有对父实体的反引用)。 >
我找到了,但不帮助我:
- 使用[JsonIgnore]导航属性将被忽略:
这个解决方案是有效的,但不适用于我的情况。例如:要获得客户信息以及其订单,我可以在订单类中快速添加[JsonIgnore]到Customer属性,但是当我想要获得订单信息以及客户详细信息时,由于客户属性[JsonIgnore] ,它不会包括客户详细信息。 - 更改JSON.Net串行器设置以保留参考:
不能保留,因为我不需要循环引用的数据。 - 禁用代理创建在数据上下文并使用显式加载(这应该理想地解决问题):
禁用代理创建停止Lazy加载并返回数据没有错误但是当我显式包括子实体,我再次得到意想不到的自我引用循环错误!错误在父实体的反向参考级别。
<任何相同线条的经验uggestions?
我尝试了所有建议的解决方案,但没有工作。结束语将JSON.Net Serializer的DefaultContractResolver覆盖到:
public class FilterContractResolver:DefaultContractResolver
{
字典<类型,列表< string>> _propertiesToIgnore;
public FilterContractResolver(Dictionary< Type,List< string>> propertiesToIgnore)
{
_propertiesToIgnore = propertiesToIgnore;
}
protected override JsonProperty CreateProperty(MemberInfo member,MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member,memberSerialization);
列表< string>忽略;
property.Ignored | =((_propertiesToIgnore.TryGetValue(member.DeclaringType,out toIgnore)|| _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType,out toIgnore))&& toIgnore.Contains(property.PropertyName) );
返回属性;
}
}
然后创建一个静态类,返回属性的字典根据控制器忽略:
public static class CriteriaDefination
{
private static Dictionary< string ,字典<类型,列表< string>>> ToIgnore = new Dictionary< string,Dictionary< Type,List< string>>>
{
{
tblCustomer,新字典< Type,List< string>> {
{
typeof(tblCustomer),new List< string> {
//包括所有
}
},
{
typeof(tblOrder),新列表< string> {
tblCustomer//忽略回参考tblCustomer
}
}
}
},
{
tblOrder,新字典< Type,List< string>> {
{
typeof(tblCustomer),新列表< string> {
tblOrders//忽略对tblOrders的引用
}
},
{
typeof(tblOrder),新列表< string> {
// include all
}
}
}
}
};
public static Dictionary< Type,List< string>> IgnoreList(string key)
{
return ToIgnore [key];
}
}
每个控制器内部都会更改JSON Formatter,如下所示:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList(tblCustomer));
JSON Serialization (ASP.Net Web API) fails because of self-referencing loop (it’s a common problem, Reason: an entity being requested lazy loads child entities and every child has a back reference to parent entity).
Work around I found, but doesn’t help me:
- Use [JsonIgnore] for navigation properties to be ignored: This solution works but doesn’t apply in my case. For Example: To get a Customer information along with his Orders, I would quickly add [JsonIgnore] to Customer property in Order class, but when I want to get an Order information along with the Customer details, since there’s [JsonIgnore] on Customer property, it won’t include Customer details.
- Change JSON.Net Serializer Settings to Preserve References: Can’t Preserve because I don’t need Circular referenced data.
- Disable Proxy Creation at the Data Context and use explicit loading(this should ideally solve the problem): Disabling proxy creation stops Lazy Loading and returns data without error, but when I explicitly Include child entities, I again the get the unexpected self-referencing loop error! The error is at the back-reference level to parent entity.
Any experiences along the same lines/suggestions?
I tried all the suggested solutions but didn't work. Ended up with Overriding the JSON.Net Serializer’s DefaultContractResolver to this:
public class FilterContractResolver : DefaultContractResolver
{
Dictionary<Type, List<string>> _propertiesToIgnore;
public FilterContractResolver(Dictionary<Type, List<string>> propertiesToIgnore)
{
_propertiesToIgnore = propertiesToIgnore;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
List<string> toIgnore;
property.Ignored |= ((_propertiesToIgnore.TryGetValue(member.DeclaringType, out toIgnore) || _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType, out toIgnore)) && toIgnore.Contains(property.PropertyName));
return property;
}
}
Then created a Static Class which returns a dictionary of Properties to be Ignored based on the Controller:
public static class CriteriaDefination
{
private static Dictionary<string, Dictionary<Type, List<string>>> ToIgnore = new Dictionary<string, Dictionary<Type, List<string>>>
{
{
"tblCustomer", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
//include all
}
},
{
typeof(tblOrder), new List<string>{
"tblCustomer"//ignore back reference to tblCustomer
}
}
}
},
{
"tblOrder", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
"tblOrders"//ignore back reference to tblOrders
}
},
{
typeof(tblOrder), new List<string>{
//include all
}
}
}
}
};
public static Dictionary<Type, List<string>> IgnoreList(string key)
{
return ToIgnore[key];
}
}
And inside every controller change the JSON Formatter something like:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList("tblCustomer"));
这篇关于获取JSON序列化实体框架自我引用即使在ProxyCreation之后循环错误,当使用显式包含时为false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!