[英]StackOverflowException on JsonConvert.DeserializeObject
I am writing a solution that contains an ASP.NET Web API (.NET 4.6.2) aka the backend, a Web API Client Implementation PCL aka the middleware and Xamarin.Forms projects aka the frontend. 我正在编写一个包含ASP.NET Web API(.NET 4.6.2)(即后端),Web API客户端实现PCL(即中间件)和Xamarin.Forms项目(即前端)的解决方案。 After recent changes to my web api I now always get a StackOverflowException when I try to deserialize the JSON response in my frontend.
在我的web api最近更改后,当我尝试在前端反序列化JSON响应时,我现在总是得到StackOverflowException。 The specific line is:
具体路线是:
result_ = JsonConvert.DeserializeObject<ObservableCollection<Employee>>(Encoding.UTF8.GetString(responseData_, 0, responseData_.Length));
When I am debugging here, I see that the program is jumping between two lines until the overflow occurs: 当我在这里调试时,我看到程序在两行之间跳转,直到发生溢出:
EmployeesManager.cs (in the middleware) EmployeesManager.cs(在中间件中)
private Image _image = new Image();
ImagesManager.cs (in the middleware) ImagesManager.cs(在中间件中)
private Employee _employee = new Employee();
Here is more code: 这是更多的代码:
The models (in the Web API): 模型(在Web API中):
public class Employee
{
public int Id { get; set; }
// OMITTED PROPS
public int? ImageId { get; set; }
public Image Image { get; set; }
public ICollection<Device> Devices { get; set; }
public int? TeamId { get; set; }
public Team Team { get; set; }
}
public class Image
{
[Key]
public int Id { get; set; }
[Required]
public byte[] Data { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
}
The models in the client implementation (middleware). 客户端实现中的模型(中间件)。 They are generated with Nswag :
它们是用Nswag生成的:
public partial class Employee : INotifyPropertyChanged
{
private int _id;
private int? _imageId;
private Image _image = new Image(); // THIS LINE IS PART OF THE OVERFLOW
private ObservableCollection<Device> _devices;
private int? _teamId;
private Team _team = new Team();
// OMITTED PROPS
[JsonProperty("image", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
public Image Image
{
get { return _image; }
set
{
if (_image != value)
{
_image = value;
RaisePropertyChanged();
}
}
}
public partial class Image : INotifyPropertyChanged
{
private int _id;
private int _employeeId;
private Employee _employee = new Employee(); // THIS LINE IS PART OF THE STACK OVERFLOW
private byte[] _data;
// OMITTED PROPS
[JsonProperty("employee", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
public Employee Employee
{
get { return _employee; }
set
{
if (_employee != value)
{
_employee = value;
RaisePropertyChanged();
}
}
}
I use the Web API client implementation via Xamarin.Forms projects. 我通过Xamarin.Forms项目使用Web API客户端实现。 The behavior is the same on all platforms.
所有平台上的行为都是相同的。 Only iOS and UWP recognize the Stack Overflow, though.
但是,只有iOS和UWP识别Stack Overflow。 On Android the app just closes without an Exception when I am reading data from the Web API.
在Android上,当我从Web API读取数据时,应用程序只关闭而没有异常。
If somebody wants to see more code, I can prepare a small package containing the requested code. 如果有人想要查看更多代码,我可以准备一个包含所请求代码的小包。 Posting them all here would break readability completely.
将它们全部发布在这里会完全破坏可读性。
I use Newtonsoft Json.NET, Entity Framework 6, NSwag 6, Xamarin.Forms v2.3.2.127. 我使用Newtonsoft Json.NET,Entity Framework 6,NSwag 6,Xamarin.Forms v2.3.2.127。
I had this happen to me before; 我之前发生过这件事; it was due to a circular reference between the objects.
这是由于对象之间的循环引用。 You have an Employee references Image and Image referencing Employee.
您有一个Employee引用Image和Image引用Employee。
Try putting a [JsonIgnore]
above the Employee property in Image the image class. 尝试将
[JsonIgnore]
放在Image的[JsonIgnore]
属性上面。
I followed the answers of Oxidda, David and EJoshuaS. 我按照Oxidda,David和EJoshuaS的回答。
Here is the complete solution for the purpose of full documentation: 以下是完整文档的完整解决方案:
I tried putting JsonIgnore on the Employee property on the Image class inside the middleware (the Web API client PCL). 我尝试将JsonIgnore放在中间件(Web API客户端PCL)内的Image类的Employee属性上。 Strangely enough that did not fix the problem.
奇怪的是,没有解决问题。 I still got the Stack Overflow with the private variables behind the properties.
我仍然使用属性后面的私有变量获得Stack Overflow。 Now I put JsonIgnore on the Employee navigation property of the Image class in the Web API (the backend) and also on the Employee navigation property of the Device class.
现在我将JsonIgnore放在Web API(后端)中的Image类的Employee导航属性上,也放在Device类的Employee导航属性上。 Then I removed the navigation properties (Employee in the image class, and Employee in the device class) completely from the API client (middleware), because JSON for those properties now will never be received, since the API will already ignore those.
然后我完全从API客户端(中间件)中删除了导航属性(图像类中的Employee和设备类中的Employee),因为现在永远不会收到这些属性的JSON,因为API已经忽略了这些属性。 The error is away now and on top I got a significant speed boost to requests and responses.
错误现在已经消失,最重要的是我对请求和响应的速度提升了很快。 Seems like although the Web API (backend) was working fine and had no issues with the relations, those navigation properties on the optional models introduced a high amount of overhead.
看起来虽然Web API(后端)工作正常并且关系没有问题,但可选模型上的那些导航属性引入了大量开销。 The classes are really small and the tables of the database are almost empty but the impact seems to be huge.
这些类非常小,数据库的表几乎是空的,但影响似乎很大。
TL;DR: Eliminated the possibility for circular reference at the source. TL; DR:消除源头循环引用的可能性。 Mirrored changes to the client.
对客户端进行镜像更改。 Problem solved and also received a huge speed boost.
问题解决了,也获得了巨大的速度提升。
If somebody is interested in the complete design of my solution, here is a small summary. 如果有人对我的解决方案的完整设计感兴趣,这里有一个小小的总结。 I like it a lot.
我很喜欢。
Basically you can just write some properties in the Web API (+ configure the JSon Serializer and the DbContext) and the rest of the whole backend and middleware is generated. 基本上你可以在Web API中编写一些属性(+配置JSon Serializer和DbContext),然后生成整个后端和中间件的其余部分。 I love it.
我喜欢它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.