两个类
public class CookingMenu
{
public int Id { get; set; }
public string Name { get; set; }
public List<MenuItem> MenuItems { get; set; }
}
public class MenuItem
{
public int Id { get; set; }
public int MenuId { get; set; }
public virtual CookingMenu CookingMenu { get; set; }
}
CookingMenu是主类,MenuItem是子类。CookingMenu包含导航属性MenuItems,MenuItem包含导航属性CookingMenu。
在控制器中,要返回CookingMenu集合的Json对象
public async Task<IActionResult> GetCustomerMenus(int customerId)
{
var menus = context.CookingMenus
.Include(m => m.MenuItems)
.Where(m => m.CustomerId == customerId);
return new JsonResult(new { success = true, menus = await menus.ToListAsync() });
}
如果不加Include方法,代码不会有任何问题,加了Include,会抛出异常:System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32。大意就是检测到不支持的对象循环,循环深度超过最大允许的深度32。
简单分析一下就知道,这实际上是一个循环引用的问题,CookingMenu类引用了MenuItem类,MenuItem中又引用了CookingMenu类,形成循环引用。序列化时就崩溃了。
网上查了一下,说安装Microsoft.AspNetCore.Mvc.NewtonsoftJson包后就可以解决这个问题。于是通过NuGet找到Microsoft.AspNetCore.Mvc.NewtonsoftJson,最新版是3.14,结果安装时报3.14只支持.net core3.1以上版本,而我的项目是.net core 3.0。于是降低版本,安装了Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.0.0,但问题并没有解决,不知道是不是版本问题。
因为异常的命名空间是System.Text.Json,于是查看这个命名空间,发现下面还有个子命名空间Serialization,在这个命名空间中看到了JsonIgnore特性,这个特性可以在序列化忽略被标注的属性。
public class MenuItem
{
public int Id { get; set; }
public int MenuId { get; set; }
[JsonIgnore]
public virtual CookingMenu CookingMenu { get; set; }
}
在MenuItem的CookingMenu属性上加上JsonIgnore特性,问题迎刃而解。
不过有个遗留问题,当属性被加上JsonIgnore特性时,我们在Linq查询中即使加上Include方法,该属性也会被忽略。这样我们就无法用Include方法来查看关联数据了。这个问题暂时没找到解决方法,以后再说吧。