我在尝试将对象转换为json时遇到问题。错误是Newtonsoft.Json.JsonSerializationException:
为属性' Project'检测到自引用循环。类型' System.Data.Entity.DynamicProxies.Project_F29F70EF89942F6344C5B0A3A7910EF55268857CD0ECC4A484776B2F4394EF79'。路径' [0] .Categories [0]'。
问题是对象(它实际上是一个对象列表)有一个属性,它是另一个引用回第一个对象的对象:
public partial class Project
{
...
public virtual ICollection<Category> Categories { get; set; }
...
}
public partial class Category
{
...
public virtual Project Project { get; set; }
...
}
就实体框架而言,这一切都很好,但是将其转换为json会导致无限回归,因此也是例外。
这是我的代码:
public async Task<HttpResponseMessage> GetProjects()
{
var projects = _projectService.GetProjects().ToList();
string jsonString = JsonConvert.SerializeObject(projects); // <-- Offending line
return Request.CreateResponse(HttpStatusCode.OK, jsonString);
}
我已经在网上寻找解决方案,我找到了这个stackoverflow帖子:
JSON.NET Error Self referencing loop detected for type
他们提出了三种解决方案,但都不起作用:
1)忽略循环引用:
public async Task<HttpResponseMessage> GetProjects()
{
var projects = _projectService.GetProjects().ToList();
JsonSerializerSettings settings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string jsonString = JsonConvert.SerializeObject(projects, settings);
return Request.CreateResponse(HttpStatusCode.OK, jsonString);
}
这导致对SerializeObject(...)的调用挂起一点然后抛出一个System.OutOfMemoryException(它告诉我循环引用没有被忽略)。
请注意,这个在stackoverflow上提出的解决方案的作者说要在WebApiConfig.cs中设置忽略设置,但我尝试了它并且没有效果。
他还说:
&#34;如果要在非api ASP.NET项目中使用此修补程序,可以将以上行添加到Global.asax.cs,但首先添加:var config = GlobalConfiguration.Configuration;&# 34;
我的网络API没有全局文件,所以我不应该这样做。
我也不想忽略循环引用,因为我不想丢失数据。
2)保留循环参考:
public async Task<HttpResponseMessage> GetProjects()
{
var projects = _projectService.GetProjects().ToList();
JsonSerializerSettings settings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
PreserveReferencesHandling = PreserveReferencesHandling.Objects
};
string jsonString = JsonConvert.SerializeObject(projects, settings);
return Request.CreateResponse(HttpStatusCode.OK, jsonString);
}
这只会导致请求超时,因为它会挂起。
同样,作者说要把它放在WebApiConfig.cs中,但这又没有效果。
3)将ignore / preserve引用属性添加到对象和属性中:
忽略类别:
public partial class Project
{
...
[JsonIgnore]
public virtual ICollection<Category> Categories { get; set; }
...
}
这没有效果。我将鼠标悬停在项目列表上,看到它仍然有类别,每个类别仍然有一个项目实例。我仍然得到同样的例外。
同样,即使这有效,我也不想忽略这些类别。
保留类别:
[JsonObject(IsReference = true)]
public partial class Project
{
...
public virtual ICollection<Category> Categories { get; set; }
...
}
同样,结果相同。
即使此方法有效,也不会保留属性。我将在每次重新编译时自动重新生成的Entity Framework类中执行此操作。 (有没有办法告诉它在模型中设置这些属性?我可以在部分类的另一半上设置它们吗?)
或者,除了转换为json并在回复中发送回来之外,我还要接受其他建议。还有另一种方法可以将数据恢复到客户端吗?
这个问题会解决什么问题?感谢。
答案 0 :(得分:1)
简言之
解决此问题的最佳方法是在Presentation层上创建完全全新的模型(xxxModel,xxxViewModel,xxxResponse等),这些模型将返回给最终用户。不只是使用AutoMapper或您自己的自定义方法将一个对象强制转换为另一个对象。
让您的数据库实体与现实世界分开!
详细
你会遇到很多问题:
还有很多其他问题,请小心。
答案 1 :(得分:0)
我建议不要序列化实体框架类并创建一个只继承自Object并且只有你需要的数据的特定类