2013-08-22 44 views
20

Tôi có một mô hình dữ liệu đơn giản liên quan đến Weeds and Weed Families.Tham khảo thông tư ngăn ngừa việc tuần tự hóa đồ thị đối tượng

WeedFamily <-1---*-> Weed (WeedFamily và cỏ dại có một-nhiều mối quan hệ)

Tôi đang cố gắng để hoàn thành ApiController đầu tiên của tôi để tôi có thể dễ dàng lấy dữ liệu của tôi như JSON cho một ứng dụng AngularJS. Khi tôi truy cập URL /WeedAPI/ trong ứng dụng của mình, tôi nhận được lỗi sau. Tôi chắc chắn vấn đề là tôi có tham chiếu vòng tròn giữa WeedWeedFamily.

Tôi nên thay đổi mô hình dữ liệu của mình sao cho việc tuần tự hóa JSON sẽ hoạt động trong khi duy trì chất lượng hai chiều của mối quan hệ Weed - WeedFamily?

(. Tức là tôi muốn vẫn có thể xây dựng biểu thức như sau:

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

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

)

Lỗi:

<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> 

Dữ liệu của tôi:

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"]) 

     }; 
    } 
} 

lớp My mô hình:

[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 + ")"; 
    } 
} 

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

Cuối cùng, ApiController:

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

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

} 
+1

Tại sao các bạn trọng 'ToString() '? Có thể bạn chỉ muốn sử dụng thuộc tính '[DebuggerDisplay]'. – ANeves

Trả lời

35

Thêm [DataContract(IsReference = true)] để các đối tượng có tham chiếu vòng tròn.

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

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

Xem http://msdn.microsoft.com/en-us/library/vstudio/hh241056(v=vs.100).aspx

+0

Tôi có cần nhập để sử dụng thuộc tính đó không? 'Không thể tìm thấy loại tên hoặc không gian tên 'DataContractAttribute' –

+1

Vâng, trong không gian tên' System.Runtime.Serialization' – Hack

+1

Biến ra tôi cần thêm 'System.Runtime.Serialization.dll' làm Tham chiếu trong dự án VS của tôi : http://stackoverflow.com/questions/7401795/namespace-for-datacontract Sau khi tôi đã làm việc serialization của tôi hoạt động chính xác! Cảm ơn. –