使用MVC3和EF4 CTP5w进行JSON序列化的循环引用异常

时间:2023-02-02 00:15:17

I'm having problems with a circular reference when i try and serialise an object returned via EF4 CTP5. Im using the code first approach and simple poco's for my model.

当我尝试并序列化通过EF4 CTP5返回的对象时,我遇到了一个循环引用的问题。我的模型使用代码优先方法和简单的poco。

I have added [ScriptIgnore] attributes to any properties that provide a back references to an object and annoyingly every seems to work fine if i manually instantiate the poco's, i.e. they serialise to JSON fine, and the scriptignore attribute is acknowledged. However when i try and serialise an object returned from the DAL i get the circular reference exception "A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.xxxx'"

我已经将[ScriptIgnore]属性添加到任何提供对对象的反向引用的属性中,而且令人讨厌的是,如果我手工实例化poco的属性,每个属性似乎都可以工作得很好,例如,它们序列化为fine JSON,并承认ScriptIgnore属性。然而,当我尝试序列化一个从DAL返回的对象时,我得到了循环引用异常“在序列化一个类型为‘System.Data.Entity.DynamicProxies.xxxx’的对象时,检测到了一个循环引用”。

I have tried several ways of retreiving the data but they all get stuck with this error:

我已经尝试了几种方法来重新将数据进行三倍化,但它们都遇到了这个错误:

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
        TimeSlot ts = tsDao.GetById(id);
        return Json(ts);
    }

The method below works slightly better as rather than the timeslot dynamic proxied object causing the circular refference its the appointment object.

下面的方法比timeslot dynamic proxied对象的效果稍好一些,后者导致循环返回其约会对象。

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
            var ts = from t in tsDao.GetQueryable()
                 where t.Id == id
                 select new {t.Id, t.StartTime, t.Available, t.Appointment};
        return Json(ts);
    }

Any ideas or solutions to this problem?

对这个问题有什么想法或解决办法吗?

Update I would prefer to use the out of the box serialiser if possible although Json.Net via nuget is ok as an alternative i would hope its possible to use it as I intended as well...

如果可能的话,我宁愿使用开箱即用的序列化器,尽管Json。Net via nuget是可以替代的,我希望它也可以像我想的那样……

5 个解决方案

#1


4  

I had a similar problem with an IIS hosted WCF service and trying to serialize POCO objects with the DataContractJsonSerializer class. The built in JSON serializer does not seem to handle circular references at all. I was able to get around it by handling the serialization myself using the JSON.net serializer, and just returning json strings from my methods. The JSON.net serializer has an option to ignore circular references as json itself does not support them.

我在IIS托管的WCF服务上遇到了类似的问题,并试图用DataContractJsonSerializer类序列化POCO对象。内建的JSON序列化器似乎根本不处理循环引用。我可以通过使用JSON.net序列化器自己处理序列化,并从方法中返回json字符串来解决这个问题。JSON.net序列化器有一个选项可以忽略循环引用,因为json本身不支持循环引用。

#2


2  

No matter what I did the dynamic proxies kept being a sticking point, I went as far as removing all circular references in my model! but still the problem persisted.

无论我做了什么动态代理都是一个症结,我甚至删除了模型中所有的循环引用!但问题依然存在。

I tried Json.Net but the same problem occurred.

我试着Json。但同样的问题也发生了。

In the end I stumbled upon a post about using a custom JavaScriptConverter

最后,我偶然发现了一篇关于使用定制javascript转换器的文章

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

Implemented the code and bobs your uncle everything worked

实现了代码并让叔叔所有的东西都工作了

#3


1  

I solved this without having to resort to an external JSON serializer. In a nutshull I disabled ProxyCreation in the constructor of my object context.

我不用借助外部JSON序列化器就解决了这个问题。在nutshull中,我在对象上下文的构造函数中禁用了ProxyCreation。

I am not sure why this works but I posted a follow up question here.

我不知道这是为什么,但我在这里贴了一个后续问题。

#4


1  

I used the following ContractResolver. Note that I inherited from the CamelCaseContractPropertyResolver to get that feature as well, but you can also inherit directly from DefaultContractResolver.

我使用了以下的收缩分解器。注意,我也从CamelCaseContractPropertyResolver继承了这个特性,但是您也可以直接从defaultcontractcontractresolver继承。

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace MyNamespace
{
    /// <summary>
    /// This class enables EntityFramework POCO objects to be serialized. In some cases POCO
    /// objects are subclassed by a proxy which has an additional member _entityWrapper. This
    /// object prevents serialization (circular references and references to non-serializable types).
    /// This removes the _entityWrapper from the list of members to be serialized.
    /// </summary>
    public class ContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (objectType.FullName.StartsWith("System.Data.Entity.DynamicProxies."))
            {
                var members = base.GetSerializableMembers(objectType);
                members.RemoveAll(memberInfo => memberInfo.Name == "_entityWrapper");
                return members;
            }
            return base.GetSerializableMembers(objectType);
        }
    }
}

To use it, create your serializer and then set the ContractResolver property to a new instance of this class:

要使用它,创建您的序列化器,然后将ContractResolver属性设置为该类的新实例:

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 

#5


0  

I have met this issue too. Answers to this topic contains number solutions. But best different solutions for different cases with explanation and moreover without custom serializes I have found in the article by Hongye Sun - Loop Reference handling in Web API.

我也遇到过这个问题。这个主题的答案包含数字解。但是对于不同的情况,最好的不同的解决方案是有解释的,而且不需要自定义序列化。

#1


4  

I had a similar problem with an IIS hosted WCF service and trying to serialize POCO objects with the DataContractJsonSerializer class. The built in JSON serializer does not seem to handle circular references at all. I was able to get around it by handling the serialization myself using the JSON.net serializer, and just returning json strings from my methods. The JSON.net serializer has an option to ignore circular references as json itself does not support them.

我在IIS托管的WCF服务上遇到了类似的问题,并试图用DataContractJsonSerializer类序列化POCO对象。内建的JSON序列化器似乎根本不处理循环引用。我可以通过使用JSON.net序列化器自己处理序列化,并从方法中返回json字符串来解决这个问题。JSON.net序列化器有一个选项可以忽略循环引用,因为json本身不支持循环引用。

#2


2  

No matter what I did the dynamic proxies kept being a sticking point, I went as far as removing all circular references in my model! but still the problem persisted.

无论我做了什么动态代理都是一个症结,我甚至删除了模型中所有的循环引用!但问题依然存在。

I tried Json.Net but the same problem occurred.

我试着Json。但同样的问题也发生了。

In the end I stumbled upon a post about using a custom JavaScriptConverter

最后,我偶然发现了一篇关于使用定制javascript转换器的文章

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

Implemented the code and bobs your uncle everything worked

实现了代码并让叔叔所有的东西都工作了

#3


1  

I solved this without having to resort to an external JSON serializer. In a nutshull I disabled ProxyCreation in the constructor of my object context.

我不用借助外部JSON序列化器就解决了这个问题。在nutshull中,我在对象上下文的构造函数中禁用了ProxyCreation。

I am not sure why this works but I posted a follow up question here.

我不知道这是为什么,但我在这里贴了一个后续问题。

#4


1  

I used the following ContractResolver. Note that I inherited from the CamelCaseContractPropertyResolver to get that feature as well, but you can also inherit directly from DefaultContractResolver.

我使用了以下的收缩分解器。注意,我也从CamelCaseContractPropertyResolver继承了这个特性,但是您也可以直接从defaultcontractcontractresolver继承。

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace MyNamespace
{
    /// <summary>
    /// This class enables EntityFramework POCO objects to be serialized. In some cases POCO
    /// objects are subclassed by a proxy which has an additional member _entityWrapper. This
    /// object prevents serialization (circular references and references to non-serializable types).
    /// This removes the _entityWrapper from the list of members to be serialized.
    /// </summary>
    public class ContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (objectType.FullName.StartsWith("System.Data.Entity.DynamicProxies."))
            {
                var members = base.GetSerializableMembers(objectType);
                members.RemoveAll(memberInfo => memberInfo.Name == "_entityWrapper");
                return members;
            }
            return base.GetSerializableMembers(objectType);
        }
    }
}

To use it, create your serializer and then set the ContractResolver property to a new instance of this class:

要使用它,创建您的序列化器,然后将ContractResolver属性设置为该类的新实例:

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 

#5


0  

I have met this issue too. Answers to this topic contains number solutions. But best different solutions for different cases with explanation and moreover without custom serializes I have found in the article by Hongye Sun - Loop Reference handling in Web API.

我也遇到过这个问题。这个主题的答案包含数字解。但是对于不同的情况,最好的不同的解决方案是有解释的,而且不需要自定义序列化。