Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中使用JavascriptSerializer序列化嵌套实体(模型)?_C#_Json_Asp.net Mvc_Nested_Javascriptserializer - Fatal编程技术网

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

如何在C#中使用JavascriptSerializer序列化嵌套实体(模型)?,c#,json,asp.net-mvc,nested,javascriptserializer,C#,Json,Asp.net Mvc,Nested,Javascriptserializer,我正在构建一个ASP.NET Web应用程序,而且我还将首先使用实体框架代码。在本例中,我使用两个实体(客户和联系人),它们彼此之间有一对多关系(一个客户可以有多个联系人)。从数据库中获取数据时,一切正常。我也使用Viewmodels,所以在我的数据实体旁边,我还有两个名为CustomerModel和ContactModel的模型 下面我将展示我的实体和视图模型: 客户实体 [Table("Customer")] public class Customer { [

我正在构建一个ASP.NET Web应用程序,而且我还将首先使用实体框架代码。在本例中,我使用两个实体(客户和联系人),它们彼此之间有一对多关系(一个客户可以有多个联系人)。从数据库中获取数据时,一切正常。我也使用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; }
    }
客户模型

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


在我的例子中,
字符串输出
不包含两个
联系人
。我如何解决这个问题?我也检查了一些关于Stackoverflow的“类似”问题,但没有结果。

好的,我发现您缺少一个概念DTO和循环引用,简单来说,您必须为您想要交付的内容制作一个模型。让你头疼的是层/参照,所以我去掉了模型中的所有循环

想象一下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: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
        };
    }
}
公共JsonResult GetCustomerById(Guid id) { CustomerModel customer=new CustomerManager().GetById(id); CustomerResultModel输出=新CustomerResultModel(){ id=customer.id, Contacts=GetContacts(customer.Contacts) }; 返回Json(输出,JsonRequestBehavior.AllowGet); //如果您只发布,那么删除AllowGet(操作名称为Get,我假设是这样的) } private IEnumerable GetContacts(联系人){ foreach(触点中的var a){ //在语句中使用yield关键字时,可以指示它出现的方法、运算符或get访问器是迭代器。 返回新的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;}
}
类CustomerResultModel{
公共Guid id{get;set;}
公共IEnumerable联系人{get;set;}
}
类ContactResultModel{
公共Guid id{get;set;}
公共Guid CustomerId{get;set;}
}

首先,不要序列化实体(这就是为什么你有数据库,创建你自己的结构来序列化(读取数据传输对象(DTO))。其次,通过序列化这样的东西,你会得到循环引用。意思是A引用B引用A(循环到无穷大),这就是为什么你必须停止以下引用,在大多数情况下,停止多个链接或一个链接中的引用将起作用,在某些情况下,你必须同时阻止这两个链接。这意味着,是的,你将有点“错过”一些数据。JSON的复杂度有一个限制,这在SQL@ThomasAndreèLian因此,如果我正确理解您的答案,那么如果我以另一种方式构建视图模型,而不使用引用来正确存储我的属性,可能会有所帮助。您是否声称
CustomerModel
ContactModel
是视图模型?如果是,则ey将没有
[Serializable]
[ScriptIgnore]
属性,并且属性将不是虚拟的。除了循环引用问题(删除
CustomerModel Customer
)之外,如果要返回Json,请使用
返回Json(客户)
是的,删除实体中的所有序列化,它们永远不属于实体。(这是一个糟糕的开始)@ThomasAndreèLian谢谢你,也在我的viewmodels中?或者只是在我的数据库实体中称为“Customer”和“Contact”?我正在尝试这个atm,当我得到结果时,我会尽快回答,如果你需要结果模型中的更多数据,你可以添加,只是不要在你的数据中做循环引用,就像你在实体中可以做的那样(多个)这最终对我有效,但与你给我的示例不同。我试图真正理解DTO,它帮助我避免了循环引用的内容。但我所做的唯一更改是删除ContactModel类中的CustomerId和CustomerModel属性,以及删除的[ScriptIgnore(ApplyToOverrides=true)]在公共虚拟列表联系人{get;set;}属性上方。执行此操作后,它工作正常,还序列化了CustomerModel对象中嵌套的ContactModel实体。感谢您的帮助Thomas!这与我的模型基本相同(它们与您提供的相同,但没有链接的PropS)正如我提到的,有时候你只需要删除其中一个方向就可以成功
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;}
}