Evg*_*y20 4 c# asp.net asp.net-mvc asp.net-core
我试图在 Include(p => p.SubCategory) 之后获取 SubCategory 并收到错误:
“Newtonsoft.Json.JsonSerializationException:‘检测到类型‘E_Store2021.Models.Product’的自引用循环。路径‘[0].Product.SubCategory.Products’”
我需要获取 SubCategoryName。这种情况我该怎么办?没有 Include() 一切正常。公司也会发生同样的情况。
标记:
<tr>
<td>
<figure class="itemside align-items-center">
<div class="aside"><img src="@("~/images/content/" + item.Product.ImagePath)" asp-append-version="true" class="img-sm"/></div>
<figcaption class="info">
<a href="#" class="title text-dark" data-abc="true">@item.Product.ProductName</a>
<p class="text-muted small">Category: <br> Brand: @item?.Product?.Company.CompanyName</p>
<p class="text-muted small">SubCategory: @item.Product?.SubCategory?.SubCategoryName</p>
</figcaption>
</figure>
</td>
<td>
<select class="form-control">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</td>
<td>
<div class="price-wrap"> <var class="price">@item.Product.UnitPrice</var> <small class="text-muted"> $9.20 each </small> </div>
</td>
<td class="text-right d-none d-md-block"> <a data-original-title="Save to Wishlist" title="" href="" class="btn btn-light" data-toggle="tooltip" data-abc="true"> <i class="fa fa-heart"></i></a> <a href="" class="btn btn-light" data-abc="true"> Remove</a> </td>
</tr>
Run Code Online (Sandbox Code Playgroud)
代码:
namespace E_Store2021.Controllers
{
public class CartController : Controller
{
private ApplicationDbContext _context;
public CartController(ApplicationDbContext context)
{
_context = context;
}
[AllowAnonymous]
public IActionResult Index()
{
var cart = SessionHelper.GetObjectFromJson<List<ShoppingCartItem>>(HttpContext.Session, "cart");
ShoppingCartModel.ShoppingCartItems = cart;
ShoppingCartModel.Total = cart?.Sum(item => item.Product.UnitPrice * item.Quantity);
return View();
}
[AllowAnonymous]
public IActionResult Buy(int id)
{
if (SessionHelper.GetObjectFromJson<List<ShoppingCartItem>>(HttpContext.Session, "cart") == null)
{
List<ShoppingCartItem> cart = new List<ShoppingCartItem>();
cart.Add(new ShoppingCartItem { Product = _context.Products.Include(p=>p.SubCategory).FirstOrDefault(p => p.ProductID == id), Quantity = 1 });
SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
}
else
{
List<ShoppingCartItem> cart = SessionHelper.GetObjectFromJson<List<ShoppingCartItem>>(HttpContext.Session, "cart");
int index = IsExist(id);
if (index != -1)
cart[index].Quantity++;
else
cart.Add(new ShoppingCartItem { Product = _context.Products.Include(p => p.SubCategory).FirstOrDefault(p => p.ProductID == id), Quantity = 1 });
SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
}
return RedirectToAction("Index");
}
[AllowAnonymous]
public IActionResult Remove(int id)
{
List<ShoppingCartItem> cart = SessionHelper.GetObjectFromJson<List<ShoppingCartItem>>(HttpContext.Session, "cart");
int index = IsExist(id);
cart.RemoveAt(index);
SessionHelper.SetObjectAsJson(HttpContext.Session, "cart", cart);
return RedirectToAction("Index");
}
[AllowAnonymous]
private int IsExist(int id)
{
List<ShoppingCartItem> cart = SessionHelper.GetObjectFromJson<List<ShoppingCartItem>>(HttpContext.Session, "cart");
for (int i = 0; i < cart.Count; i++)
{
if (cart[i].Product.ProductID.Equals(id))
return i;
}
return -1;
}
}
}
Run Code Online (Sandbox Code Playgroud)
会话助手。尝试序列化对象时,此处会发生错误。
public static class SessionHelper
{
public static void SetObjectAsJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObjectFromJson<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonConvert.DeserializeObject<T>(value);
}
}
Run Code Online (Sandbox Code Playgroud)
不确定您是否已经解决了这个问题,因为昨天有人问过这个问题,或者为什么没有反应。
当对象结构中存在循环引用时,这是一个经常遇到的问题。最佳实践是首先在 DTO/视图模型中避免这些。
但是,如果您可以从序列化中排除这些循环引用,那么您很幸运,因为您使用的是 Newtonsoft JSON,它支持通过选项配置此行为JsonSerializerSettings.ReferenceLoopHandling。
我认为这在这里应该足够了,因为自引用似乎发生在Products.SubCategory和之间SubCategory.Products,而您想要的是SubCategory.Name,它仍然应该被填充。
如果使用此设置不可行,您可以只定义一个 ProductDto 或 ProductViewModel,它们甚至可能会展平层次结构,并且除了其他属性之外还包含一个属性,SubCategoryName而不是包含整个SubCategory实体(或者无论如何都适合您)。
有三种方法可以使用上述选项。
services.AddMvc()
.AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
Run Code Online (Sandbox Code Playgroud)
AddNewtonsoftJson()请记住,如果您使用的是 ASP.NET Core 3+,并且事先配置中没有现有调用,则执行此操作会将 Microsoft 的新System.Text.Json序列化器替换为 Newtonsoft 的序列化器(速度较慢)。
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
// Then all subsequent manual serialization will be done with this setting.
string json = JsonConvert.SerializeObject (object);
Run Code Online (Sandbox Code Playgroud)
请注意,以这种方式配置它不会更改 ASP.NET Core 控制器操作的行为,因为该序列化似乎使用单独的设置实例。
JsonSerializerSettings当您手动序列化时,每次显式传递一个实例:JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
};
string json = JsonConvert.SerializeObject (object, settings);
Run Code Online (Sandbox Code Playgroud)
因此,对于您的情况,解决方案 2) 或 3) 就是您所需要的。感谢您的编辑;在我原来的回答中,我没有考虑到您正在手动调用SerializeObject().
| 归档时间: |
|
| 查看次数: |
13121 次 |
| 最近记录: |