如何在 C# 中使用 JavascriptSerializer 序列化嵌套实体(模型)?

How to serialize a nested entity (model) with JavascriptSerializer in C#?

我正在构建一个 ASP.NET 网络应用程序,我也在使用 Entity Framework 代码优先。在这种情况下,我使用两个实体(客户和联系人),它们彼此之间具有一对多关系(一个客户可以有多个联系人)。从数据库中获取数据时,一切正常。我还使用 Viewmodels,所以在我的数据实体旁边,我还有两个模型,分别称为 CustomerModel 和 ContactModel。

下面我将展示我的实体和视图模型:

客户实体

[Table("Customer")]
    public class Customer
    {
        [Key()]
        public Guid Id { get; set; }
        //other non-relevant properties
        public virtual List<Contact> Contacts { get; set; }
    }

联系人实体

[Table("Contact")]
    public class Contact
    {
        [Key()]
        public Guid Id { get; set; }
        //non-relevant properties
        [ForeignKey("Customer")]
        public Guid CustomerId { get; set; }
        [Required]
        public virtual Customer Customer { get; set; }
    }

客户模型

[Serializable]
    public class CustomerModel
    {
        public Guid Id { get; set; }
        //non-relevant properties
        [ScriptIgnore(ApplyToOverrides = true)]
        public virtual List<ContactModel> Contacts { get; set; }
    }

联系人模型

[Serializable]
    public class ContactModel
    {
        public Guid Id { get; set; }
        //non-relevant properties
        public Guid CustomerId { get; set; }
        [ScriptIgnore(ApplyToOverrides = true)]
        public virtual CustomerModel Customer { get; set; }
    }

当我 运行 我的应用程序和代码时,它在后端都运行良好,直到它需要在我的 HomeController 中将其序列化为 JSON。

public ActionResult GetCustomerById(Guid id)
        {
            CustomerModel customer = new CustomerManager().GetById(id);
            string output = serializer.Serialize(customer);
            return Content(output);
        }

即使 CustomerModel 对象也获得了 2 个联系人,但在我的 Serialize(customer) 方法中,它不会将其解析为 JSON。所以实际上,当我调试它并查看我的输出时,我看到了每个 属性 但没有看到嵌套的 ContactModels。

在我的例子中,string output 不包含两个 Contacts。我该如何解决这个问题?我也在 Whosebug 上检查了一些 'similar' 个问题,但没有结果。

好的,我发现您缺少概念 DTO 和循环引用,简单来说,您必须为要交付的内容制作模型。困扰你的是 layers/refferences,所以我消除了模型中的所有循环。

想想 a -> b -> a 会导致 json 看起来像这样

{ a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a:b{a}}}}}}}}}} //进入无穷远 }

这本质上就是您想要的。

public JsonResult GetCustomerById(Guid id)
{
    CustomerModel customer = new CustomerManager().GetById(id);
    CustomerResultModel output = new CustomerResultModel(){
        id = customer.Id,
        Contacts = GetContacts(customer.Contacts)
    };
    return Json(output, JsonRequestBehavior.AllowGet); 
    //If you only POST then remove the AllowGet (the action name says Get so I'm assuming
}
private IEnumerable<ContactResultModel> GetContacts(Contacts){
    foreach(var a in Contacts){
        //When you use the yield keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator.
        yield return new ContactResultModel(){            
            Id  = a.Id,
            CustomerId = a.CustomerId
        };
    }
}

型号

class CustomerResultModel{
    public Guid id {get;set;}
    public IEnumerable<ContactResultModel> Contacts {get;set;}
}

class ContactResultModel{
    public Guid id {get;set;}
    public Guid CustomerId {get;set;}
}