c# - Circular references preventing serialization of object graph -


i've got simple data model involving weeds , weed families.

weedfamily <-1---*-> weed (weedfamily , weed have one-to-many relationship)

i'm attempting complete first apicontroller can retrieve data json angularjs application. when access /weedapi/ url in application, following error. i'm pretty sure problem have circular references between weed , weedfamily.

how should change data model json serialization work while maintaining bi-directional quality of weed-weedfamily relationship?

(ie. want still able build expressions following:

 weeddata.getfamilies()["mustard"].weeds.count 

and

weeddata.getweeds()[3].family.weeds 

)

the error:

<error>     <message>an error has occurred.</message>     <exceptionmessage>         'objectcontent`1' type failed serialize response body content type 'application/xml; charset=utf-8'.     </exceptionmessage>     <exceptiontype>system.invalidoperationexception</exceptiontype>     <stacktrace/>     <innerexception>         <message>an error has occurred.</message>         <exceptionmessage>             object graph type 'weedcards.models.weedfamily' contains cycles , cannot serialized if reference tracking disabled.         </exceptionmessage>         <exceptiontype>             system.runtime.serialization.serializationexception         </exceptiontype>         <stacktrace>             @ system.runtime.serialization.xmlobjectserializerwritecontext.onhandlereference(xmlwriterdelegator xmlwriter, object obj, boolean cancontaincyclicreference) @ writeweedtoxml(xmlwriterdelegator , object , xmlobjectserializerwritecontext , classdatacontract ) @ system.runtime.serialization.classdatacontract.writexmlvalue(xmlwriterdelegator xmlwriter, object obj, xmlobjectserializerwritecontext context) @ system.runtime.serialization.xmlobjectserializerwritecontext.writedatacontractvalue(datacontract datacontract, xmlwriterdelegator xmlwriter, object obj, runtimetypehandle declaredtypehandle) @ system.runtime.serialization.xmlobjectserializerwritecontext.serializewithoutxsitype(datacontract datacontract, xmlwriterdelegator xmlwriter, object obj, runtimetypehandle declaredtypehandle) @ system.runtime.serialization.xmlobjectserializerwritecontext.internalserialize(xmlwriterdelegator xmlwriter, object obj, boolean isdecl...etc         </stacktrace>     </innerexception> </error> 

my data:

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

my model classes:

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

and

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

finally, apicontroller:

public class weedapicontroller : apicontroller {     //     // get: /weedapi/      public ienumerable<weed> getallweeds()     {         return weeddata.getweeds();     }  } 

add [datacontract(isreference = true)] objects have circular references.

[serializable] [datacontract(isreference = true)] public class weedfamily  [serializable] [datacontract(isreference = true)] public class weed 

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