带有MVC3和EF4 CTP5w的JSON序列化的循环引用异常

时间:2011-01-05 16:05:37

标签: c# asp.net entity-framework-4 asp.net-mvc-3 entity-framework-ctp5

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

我已经将[ScriptIgnore]属性添加到任何提供对对象的反向引用的属性中,并且令人烦恼的是,如果我手动实例化poco的话,每个似乎工作正常,即它们串行化为JSON,并且确认了scriptignore属性。但是,当我尝试序列化从DAL返回的对象时,我得到循环引用异常“序列化'System.Data.Entity.DynamicProxies.xxxx'类型的对象时检测到循环引用”

我尝试了几种检索数据的方法,但他们都遇到了这个错误:

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

下面的方法效果稍好,而不是时间段动态代理对象导致循环引用其为约会对象。

    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);
    }

这个问题的任何想法或解决方案?

更新 如果可能的话,我宁愿使用开箱即用的序列化器,尽管Json.Net通过nuget可以替代我希望它可以像我预期的那样使用它...

5 个答案:

答案 0 :(得分:4)

我遇到了与IIS托管的WCF服务类似的问题,并尝试使用DataContractJsonSerializer类序列化POCO对象。内置的JSON序列化程序似乎根本不处理循环引用。通过使用JSON.net序列化程序自己处理序列化,并从我的方法返回json字符串,我能够绕过它。 JSON.net序列化程序可以选择忽略循环引用,因为json本身不支持它们。

答案 1 :(得分:2)

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

我尝试过Json.Net,但同样的问题也出现了。

最后,我偶然发现了一篇关于使用自定义JavaScriptConverter

的帖子

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

实施代码并让你叔叔一切顺利

答案 2 :(得分:1)

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

我不确定为什么会这样,但我发布了一个跟进问题here.

答案 3 :(得分:1)

我使用了以下的ContractResolver。请注意,我继承了CamelCaseContractPropertyResolver以获取该功能,但您也可以直接从DefaultContractResolver继承。

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);
        }
    }
}

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

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

答案 4 :(得分:0)

我也遇到过这个问题。本主题的答案包含数字解决方案。但是针对不同案例的最佳不同解决方案有解释,而且没有自定义序列化我在文章中找到了 Hongye Sun - Loop Reference handling in Web API