Exception de la référence circulaire avec la sérialisation JSON avec MVC3 et EF4 CTP5w

j'ai des problèmes avec une référence circulaire quand j'essaie de sérialiser un objet retourné via EF4 CTP5. Im en utilisant l'approche du premier code et simple poco pour mon modèle.

j'ai ajouté des attributs [ScriptIgnore] à toutes les propriétés qui fournissent des références en arrière à un objet et, ce qui est fâcheux, toutes semblent fonctionner correctement si j'instancie manuellement les poco, c'est-à-dire qu'elles sérialisent à JSON fine, et l'attribut scriptignore est reconnu. Cependant lorsque je l'ai essayer et serialise un objet retourné du DAL j'obtiens l'exception de référence circulaire "une référence circulaire a été détectée lors de la sérialisation d'un objet de type 'Système.Données.Entité.DynamicProxies.xxxx""

j'ai essayé plusieurs façons de Retreiver les données mais elles sont toutes bloquées avec cette erreur:

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

la méthode ci-dessous fonctionne un peu mieux que l'objet dynamic proxied de timeslot causant la différence circulaire son l'objet appointment.

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

Tout des idées ou des solutions à ce problème?

mise à Jour Je préférerais utiliser le hors de la boîte serialiser si possible bien que Json.Net via nuget est ok comme alternative j'espère qu'il est possible de l'utiliser comme je l'avais prévu...

13
demandé sur nakchak 2011-01-05 19:05:37

5 réponses

j'ai eu un problème similaire avec un service hébergé par IIS WCF et en essayant de sérialiser les objets POCO avec la classe DataContractJsonSerializer. Le serializer JSON intégré ne semble pas traiter des références circulaires du tout. J'ai pu le contourner en manipulant la sérialisation moi-même en utilisant le JSON.net serializer, and just returning JSON strings from my methods. Les JSON.net serializer a une option pour ignorer les références circulaires comme json lui-même ne supporte pas ils.

4
répondu JMorgan 2011-01-05 20:22:36

peu importe ce que j'ai fait les mandataires dynamiques continuaient d'être un point de blocage, je suis allé jusqu'à enlever toutes les références circulaires dans mon modèle! mais le problème a persisté.

j'ai essayé Json.Net mais le même problème s'est produit.

À la fin je suis tombé sur un post à ce sujet en utilisant une mesure JavaScriptConverter

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

mise en oeuvre du code et il a volé à ton oncle tout ce qui marchait!--1-->

2
répondu nakchak 2011-01-06 12:50:47

j'ai résolu ce problème sans avoir à recourir à un serialiseur externe JSON. En un mot, j'ai désactivé ProxyCreation dans le constructeur de mon contexte objet.

Je ne sais pas pourquoi cela fonctionne mais j'ai posté une question de suivi ici.

1
répondu trevorc 2017-05-23 12:06:26

j'ai utilisé la solution de contrat suivante. Notez que j'ai hérité de la CamelCaseContractPropertyResolver pour obtenir cette fonctionnalité ainsi, mais vous pouvez également hériter directement de Defaultcontrresolver.

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

pour l'utiliser, Créez votre serializer puis définissez la propriété ContractResolver à une nouvelle instance de cette classe:

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 
1
répondu holmes 2011-11-15 15:06:19

j'ai rencontré ce problème aussi. Les réponses à ce sujet contient des solutions de nombres. Mais les meilleures solutions différentes pour les différents cas avec l'explication et de plus sans sérialise personnalisé j'ai trouvé dans l'article de Le Hongye Soleil - gestion des références de boucle dans L'API Web.

0
répondu RredCat 2013-04-16 11:35:38