循环引用$对象图的对$ pventing系列化 [英] Circular references preventing serialization of object graph

查看:295
本文介绍了循环引用$对象图的对$ pventing系列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有涉及杂草及其家庭提供简单的数据模型。

WeedFamily< -1 --- * - >杂草(WeedFamily和杂草有一到一对多的关系)

我试图完成我的第一个ApiController,这样我可以轻松地检索我的数据作为JSON用于AngularJS应用。当我在应用程序访问 / WeedAPI / URL,我得到以下错误。我是pretty确定问题是,我有之间循环引用杂草 WeedFamily

我应该如何改变我的数据模型,使同时保持双向品质JSON序列化将工作杂草 - WeedFamily 关系?

(即我希望仍然能够建立前pressions这样的:

  WeedData.GetFamilies()[芥末。Weeds.Count

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

错误:

 <错误>
    <消息方式>发生错误< /信息>
    < ExceptionMessage>
        在'ObjectContent`1类型没有序列化响应正文内容类型application / xml进行;字符集= UTF-8。
    < / ExceptionMessage>
    < ExceptionType> System.InvalidOperationException< / ExceptionType>
    <堆栈跟踪/>
    <&的InnerException GT;
        <消息方式>发生错误< /信息>
        < ExceptionMessage>
            类型对象图WeedCards.Models.WeedFamily'包含周期,如果参考禁止追踪无法被序列化。
        < / ExceptionMessage>
        < ExceptionType>
            System.Runtime.Serialization.SerializationException
        < / ExceptionType>
        <&栈跟踪GT;
            在System.Runtime.Serialization.XmlObjectSerializerWriteContext.OnHandleReference(XmlWriterDelegator的XmlWriter,obj对象,布尔canContainCyclicReference)在WriteWeedToXml(XmlWriterDelegator,对象,XmlObjectSerializerWriteContext,ClassDataContract)在System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator的XmlWriter,obj对象,XmlObjectSerializerWriteContext背景)在System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract,XmlWriterDelegator的XmlWriter,obj对象,的RuntimeTypeHandle declaredTypeHandle)在System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract,XmlWriterDelegator的XmlWriter,obj对象,的RuntimeTypeHandle declaredTypeHandle)的系统。 Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator的XmlWriter,obj对象,布尔isDecl ...等
        < /堆栈跟踪>
    < /&的InnerException GT;
< /错误>

我的数据:

 公共类WeedData
{
    公共静态字典<字符串,WeedFamily> GetFamilies(){
        返回新字典<字符串,WeedFamily>
        {
             {芥末,新WeedFamily(芥末,十字花科)}
            ,{藜,新WeedFamily(藜,苋)}
            {向日葵,新WeedFamily(向日葵,菊科)}
        };
    }    公共静态列表<杂草> GetWeeds(){
        VAR家庭= GetFamilies();
        返回新的List<杂草>
        {
             新的杂草(毛Bittercress,碎米荠,家庭[芥末])
            ,新的杂草(小Bittercress,碎米oligosperma家庭[芥末])
            ,新的杂草(荠菜,荠菜,家庭[芥末])
            ,新的杂草(野芥菜,野芥/田芥,家庭[芥末])
            ,新的杂草(野萝卜,野萝卜,家庭[芥末])
            ,新的杂草(萝卜,萝卜,家庭[芥末])
            ,新的杂草(反枝苋,反枝苋,家庭[猪草])
            ,新的杂草(野莴苣,野莴苣,家庭[向日葵])
            ,新的杂草(刺苦菜,花叶滇苦菜,家庭[向日葵])
            ,新的杂草(「股东周年苦菜,荼,家庭[向日葵])        };
    }
}

我的模型类:

  [Serializable接口]
公共类杂草
{
    公共字符串通用名称;
    公共字符串LatinName;
    公开名单< WeedPhoto>相片;
    公共WeedFamily家庭;    公共杂草(字符串COMMONNAME,串latinName)
    {
        通用名称=通用名称;
        LatinName = latinName;
    }    公共杂草(字符串COMMONNAME,串latinName,WeedFamily家族)
    {
        通用名称=通用名称;
        LatinName = latinName;
        家庭=家庭;
        Family.Weeds.Add(本);
    }    覆盖公共字符串的ToString()
    {
        返回通用名称+(+ LatinName +);
    }
}

  [Serializable接口]
公共类WeedFamily
{
    公共字符串通用名称;
    公共字符串LatinName;
    公开名单<杂草>杂草;    公共WeedFamily(字符串COMMONNAME,串latinName)
    {
        通用名称=通用名称;
        LatinName = latinName;
        杂草=新的List<杂草>();
    }
}

最后,ApiController:

 公共类WeedAPIController:ApiController
{
    //
    // GET:/ WeedAPI /    公共IEnumerable的<杂草> GetAllWeeds()
    {
        返回WeedData.GetWeeds();
    }}


解决方案

添加 [DataContract(IsReference = TRUE)] 来有循环引用的对象。

  [Serializable接口]
[DataContract(IsReference =真)]
公共类WeedFamily[Serializable接口]
[DataContract(IsReference =真)]
公共类杂草

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

I've got a simple data model involving Weeds and Weed Families.

WeedFamily <-1---*-> Weed (WeedFamily and Weed have a one-to-many relationship)

I'm attempting to complete my first ApiController so that I can easily retrieve my data as JSON for an AngularJS application. When I access the /WeedAPI/ URL in my application, I get the following error. I'm pretty sure the problem is that I have circular references between Weed and WeedFamily.

How should I change my data model so that the JSON serialization will work while maintaining the bi-directional quality of the Weed-WeedFamily relationship?

(ie. I want to still be able to build expressions like the following:

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

and

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

)

The error:

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

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, the ApiController:

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

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

}

解决方案

Add [DataContract(IsReference = true)] to the objects that 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

这篇关于循环引用$对象图的对$ pventing系列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆