2013-08-22 13 views
20

Weeds ve Weed Families'i içeren basit bir veri modelim var.Nesne grafiğinin serileşmesini önleyen dairesel referanslar

WeedFamily <-1---*-> Weed ben kolayca angularjs uygulama için JSON olarak benim veri almak, böylece ilk ApiController tamamlamak çalışılıyor

(WeedFamily ve Ot bire çok ilişki var). Uygulamamda /WeedAPI/ URL'ye eriştiğimde, aşağıdaki hatayı alıyorum. Sorun şu ki, Weed ve WeedFamily arasında dairesel referanslarım var.

Veri modelimi, JSON serileştirmesi Weed - WeedFamily ilişkisinin iki yönlü kalitesini koruyarak çalışacak şekilde nasıl değiştirmeliyim?

(. Yani ben hala gibi ifadeler inşa etmek mümkün istiyorum aşağıdadır:

WeedData.GetFamilies()["mustard"].Weeds.Count 

ve

WeedData.GetWeeds()[3].Family.Weeds 

)

hatası:

<Error> 
    <Message>An error has occurred.</Message> 
    <ExceptionMessage> 
     The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'. 
    </ExceptionMessage> 
    <ExceptionType>System.InvalidOperationException</ExceptionType> 
    <StackTrace/> 
    <InnerException> 
     <Message>An error has occurred.</Message> 
     <ExceptionMessage> 
      Object graph for type 'WeedCards.Models.WeedFamily' contains cycles and cannot be serialized if reference tracking is disabled. 
     </ExceptionMessage> 
     <ExceptionType> 
      System.Runtime.Serialization.SerializationException 
     </ExceptionType> 
     <StackTrace> 
      at System.Runtime.Serialization.XmlObjectSerializerWriteContext.OnHandleReference(XmlWriterDelegator xmlWriter, Object obj, Boolean canContainCyclicReference) at WriteWeedToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract) at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDecl...etc 
     </StackTrace> 
    </InnerException> 
</Error> 

Verilerim:

public class WeedData 
{ 
    public static Dictionary<string,WeedFamily> GetFamilies(){ 
     return new Dictionary<string,WeedFamily> 
     { 
      {"mustard",new WeedFamily("Mustard","Brassicaceae")} 
      ,{"pigweed",new WeedFamily("Pigweed","Amaranthus")} 
      ,{"sunflower",new WeedFamily("Sunflower","Asteraceae")} 
     }; 
    } 

    public static List<Weed> GetWeeds(){ 
     var Families = GetFamilies(); 
     return new List<Weed> 
     { 
      new Weed("Hairy Bittercress","Cardamine hirsuta",Families["mustard"]) 
      ,new Weed("Little Bittercress","Cardamine oligosperma",Families["mustard"]) 
      ,new Weed("Shepherd's-Purse","Capsella bursa-pastoris",Families["mustard"]) 
      ,new Weed("Wild Mustard","Sinapis arvensis/Brassica kaber",Families["mustard"]) 
      ,new Weed("Wild Radish","Raphanus raphanistrum",Families["mustard"]) 
      ,new Weed("Radish","Raphanus sativus",Families["mustard"]) 
      ,new Weed("Redroot Pigweed","Amaranthus retroflexus",Families["pigweed"]) 
      ,new Weed("Prickly Lettuce","Lactuca serriola",Families["sunflower"]) 
      ,new Weed("Spiny Sowthistle","Sonchus asper",Families["sunflower"]) 
      ,new Weed("Annual Sowthistle","Sonchus oleraceus",Families["sunflower"]) 

     }; 
    } 
} 

Benim modelim sınıfları:

[Serializable] 
public class Weed 
{ 
    public string CommonName; 
    public string LatinName; 
    public List<WeedPhoto> Photos; 
    public WeedFamily Family; 

    public Weed(string commonName, string latinName) 
    { 
     CommonName = commonName; 
     LatinName = latinName; 
    } 

    public Weed(string commonName, string latinName, WeedFamily family) 
    { 
     CommonName = commonName; 
     LatinName = latinName; 
     Family = family; 
     Family.Weeds.Add(this); 
    } 

    override public string ToString() 
    { 
     return CommonName + " (" + LatinName + ")"; 
    } 
} 

ve Nihayet

[Serializable] 
public class WeedFamily 
{ 
    public string CommonName; 
    public string LatinName; 
    public List<Weed> Weeds; 

    public WeedFamily(string commonName, string latinName) 
    { 
     CommonName = commonName; 
     LatinName = latinName; 
     Weeds = new List<Weed>(); 
    } 
} 

, ApiController:

public class WeedAPIController : ApiController 
{ 
    // 
    // GET: /WeedAPI/ 

    public IEnumerable<Weed> GetAllWeeds() 
    { 
     return WeedData.GetWeeds(); 
    } 

} 
+1

görüyor musunuz? Muhtemelen sadece [DebuggerDisplay] özelliğini kullanmak istersiniz. – ANeves

cevap

35

dairesel referansları var nesnelere [DataContract(IsReference = true)] ekleyin.

[Serializable] 
[DataContract(IsReference = true)] 
public class WeedFamily 

[Serializable] 
[DataContract(IsReference = true)] 
public class Weed 

Neden `ToString()` geçersiz kılma http://msdn.microsoft.com/en-us/library/vstudio/hh241056(v=vs.100).aspx

+0

Bu özelliği kullanmak için içe aktarma ihtiyacım var mı? ''DataContractAttribute' türünü veya ad alanını ' –

+1

bulunamadı' Evet System.Runtime.Serialization' ad alanı içinde – Hack

+1

Çıkıyor 'System.Runtime.Serialization.dll' benim VS projemde bir başvuru olarak eklemem gerekiyor. : http://stackoverflow.com/questions/7401795/namespace-for-datacontract Bunu yaptıktan sonra serileştirmem doğru şekilde çalıştı! Teşekkürler. –