Исключение циклической ссылки с JSON Сериализация с MVC3 и EF4 CTP5w
У меня возникают проблемы с круговой ссылкой, когда я пытаюсь сериализовать объект, возвращенный через 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 в порядке как альтернатива, я бы надеялся, что его можно будет использовать, как я и предполагал...
Ответы
Ответ 1
У меня была аналогичная проблема с IIS-сервисом WCF и попыткой сериализации объектов POCO с классом DataContractJsonSerializer. Встроенный сериализатор JSON, похоже, вообще не обрабатывает циклические ссылки. Я смог обойти это, самостоятельно обработав сериализацию, используя сериализатор JSON.net и просто возвращаю строки json из моих методов. Сериализатор JSON.net имеет возможность игнорировать циклические ссылки, поскольку сам json не поддерживает их.
Ответ 2
Независимо от того, что я делал, динамические прокси-серверы продолжали оставаться липкой, я дошел до удаления всех круговых ссылок в моей модели! но проблема продолжалась.
Я попробовал Json.Net, но возникла одна и та же проблема.
В конце концов я наткнулся на сообщение об использовании пользовательского JavaScriptConverter
http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
Реализован код и бобы дяди все работает
Ответ 3
Я решил это, не прибегая к внешнему сериализатору JSON. В nutshull я отключил ProxyCreation в конструкторе контекста моего объекта.
Я не уверен, почему это работает, но я разместил следующий вопрос здесь.
Ответ 4
Я использовал следующий 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();
Ответ 5
Я тоже встречался с этой проблемой. Ответы на эту тему содержат числовые решения. Но лучшие решения для разных случаев с объяснением и, кроме того, без пользовательских сериализаций, я нашел в статье Hongye Sun - Loop Обработка ссылок в веб-API.