Исключение циклической ссылки с сериализацией JSON с MVC3 и EF4 CTP5w - PullRequest
13 голосов
/ 05 января 2011

У меня проблемы с циклической ссылкой, когда я пытаюсь сериализовать объект, возвращенный через 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 ]

4 голосов
/ 05 января 2011

У меня была похожая проблема с размещенной в IIS службой WCF и при попытке сериализации объектов POCO с помощью класса DataContractJsonSerializer. Кажется, встроенный сериализатор JSON вообще не обрабатывает циклические ссылки. Я смог обойти это, самостоятельно выполняя сериализацию с использованием сериализатора JSON.net и просто возвращая строки json из моих методов. Сериализатор JSON.net имеет возможность игнорировать циклические ссылки, так как сам json их не поддерживает.

2 голосов
/ 06 января 2011

Независимо от того, что я делал, динамические прокси оставались камнем преткновения, я дошел до удаления всех циклических ссылок в моей модели! но проблема все еще сохраняется.

Я пробовал Json.Net, но возникла та же проблема.

В итоге я наткнулся на сообщение об использовании пользовательского JavaScriptConverter

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

Реализовал код и качнул твой дядя все заработало

1 голос
/ 15 ноября 2011

Я использовал следующий 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(); 
1 голос
/ 21 января 2011

Я решил это, не прибегая к внешнему сериализатору JSON.Вкратце я отключил ProxyCreation в конструкторе контекста моего объекта.

Я не уверен, почему это работает, но я разместил следующий вопрос здесь.

0 голосов
/ 16 апреля 2013

Я тоже встречался с этой проблемой.Ответы на эту тему содержат числовые решения.Но лучшие разные решения для разных случаев с объяснением и, более того, без пользовательских сериализаций я нашел в статье Hongye Sun - Обработка циклических ссылок в Web API .

...