简体   繁体   English

返回JSON时的C#递归限制

[英]C# recursion limit when returning JSON

I ran into an annoying issue recently. 我最近遇到了一个恼人的问题。 I'm going to simplify my datamodel here, but the principle is just the same. 我将在这里简化我的数据模型,但原理是一样的。 I have a class "User". 我有一个班级“用户”。 In that class I have a property that is a list of objects the user owns. 在该类中,我有一个属性,该属性是用户拥有的对象列表。 I also have this class "object". 我也有这个类“对象”。 Because every "object" has an owner, it has a property of type "User", which links to its owner. 因为每个“对象”都有一个所有者,所以它具有“User”类型的属性,该属性链接到其所有者。 Now, what I'm trying to do is basically this 现在,我想要做的基本上就是这个

return Json(myUser,JsonRequestBehavior.AllowGet);

When I load the page, it takes like 30 seconds and then I get the error "RecursionLimit exceeded". 当我加载页面时,它需要30秒,然后我得到错误“超过RecursionLimit”。

I guess this is because the objects are linking to each other. 我想这是因为对象是相互链接的。 Now my question is, how can I tell "Json" that it shouldn't go deeper then 1 level of objects to avoid this? 现在我的问题是,我怎么能告诉“Json”它不应该深入到1级对象以避免这种情况?

myUser is probably a type generated by EntityFramework. myUser可能是EntityFramework生成的类型。

When you return Json, the framework is going to prepare each property in essence firing off SQL command to lazy-load all the data. 当你返回Json时,框架将准备每个属性实质上触发SQL命令以延迟加载所有数据。

Instead, you should prepare a ViewModel class with concrete properties not attached to EntityFramework and prepare that object as deep as you want it to go. 相反,您应该准备一个具有未附加到EntityFramework的具体属性的ViewModel类,并准备该对象尽可能深。

It might happen when your object has some properties of itself. 当你的对象有自己的某些属性时,可能会发生这种情况 for example. 例如。

public object Employee()
{
    string ID {get; set;}
    string Name {get; set;}
    int Age {get; set;}
    Employee Boss{get; set;} //<-- here
}

var employee = new Employee();
return Json(employee,JsonRequestBehavior.AllowGet); //The Boss property will cause "RecursionLimit exceeded".

To avoid that. 为了避免这种情况 you can do something like that: 你可以这样做:

var employee = new Employee();
var prepareForJson = new {
    ID = employee.ID,
    Name = employee.Name,
    Age = employee.Age,
    Boss = employee.Boss.ID
};
return Json(prepareForJson , JsonRequestBehavior.AllowGet);

You can configure recursion depth through web.config 您可以通过web.config配置递归深度

http://msdn.microsoft.com/en-us/library/bb763183.aspx http://msdn.microsoft.com/en-us/library/bb763183.aspx

but you probably just want to sort out your model not to have recursion in the first place. 但你可能只是想弄清楚你的模型具备递归摆在首位。 Think how much data is needed in your current situation and return just that. 想想当前情况下需要多少数据并返回。

I think Edison Chuang is the answer for the vast majority of cases (mapping data models to some service models that do not have those navigation properties that will most certainly cause loops during the serialization). 我认为Edison Chuang是绝大多数案例的答案(将数据模型映射到一些服务模型,这些服务模型没有那些在序列化过程中肯定会导致循环的导航属性)。

However, since most of the service models will share many of the properties of the data models (EF models), AutoMapper can be used, greatly simplifying code especially for objects with many properties. 但是,由于大多数服务模型将共享数据模型的许多属性(EF模型),因此可以使用AutoMapper ,大大简化了代码,尤其是对于具有许多属性的对象。 Eg: 例如:

// set up map
cfg.CreateMap<Employee, EmployeeSm>();

// use the map
var sm = Mapper.Map<EmployeeSm>(employee);
// this can be also set up during mapping configuration phase
sm.Boss = employee.Boss.ID;

For those rare cases when serialization depth goes beyond the default 100, you can either increase this limit or use Json.NET to serialize your objects. 对于序列化深度超出默认值100的极少数情况,您可以增加此限制或使用Json.NET来序列化对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM