【问题标题】:CollectionDataContract not recognizing DataContractCollectionDataContract 无法识别 DataContract
【发布时间】:2017-03-11 07:01:37
【问题描述】:

我正在尝试从 WebInvoke POST 调用中使用 XML。反映XML结构和XML本身的主要类如下:

XML:

<GraphicArea>
  <AnimationID>String content</AnimationID>
  <AutoRetract>true</AutoRetract>
  <ClientID>2147483647</ClientID>
  <Description>String content</Description>
  <GraphicDetails>
    <GraphicDetail xmlns="http://schemas.datacontract.org/2004/07/fogREST">
      <GraphicID>String content</GraphicID>
      <PropFileDescription>String content</PropFileDescription>
      <PropFileID>String content</PropFileID>
      <PropName>String content</PropName>
      <PropValue>String content</PropValue>
    </GraphicDetail>
    <GraphicDetail xmlns="http://schemas.datacontract.org/2004/07/fogREST">
      <GraphicID>String content</GraphicID>
      <PropFileDescription>String content</PropFileDescription>
      <PropFileID>String content</PropFileID>
      <PropName>String content</PropName>
      <PropValue>String content</PropValue>
    </GraphicDetail>
  </GraphicDetails>
  <GraphicSubTypeID>String content</GraphicSubTypeID>
  <GraphicTypeID>String content</GraphicTypeID>
  <GraphicTypeTemplateID>String content</GraphicTypeTemplateID>
  <OffsetX>2147483647</OffsetX>
  <OffsetY>2147483647</OffsetY>
  <OffsetZ>2147483647</OffsetZ>
  <TimeCodeIn>String content</TimeCodeIn>
  <TimeCodeOut>String content</TimeCodeOut>
  <UserID>2147483647</UserID>
</GraphicArea>

数据合约:

[DataContract(Name = "GraphicArea", Namespace = "")]
public class GraphicArea
{
    [DataMember(Name = "ClientID")]
    public virtual int ClientID
    {
        get;
        set;
    }
    [DataMember(Name = "AnimationID")]
    public virtual string AnimationID
    {
        get;
        set;
    }
    [DataMember(Name = "GraphicTypeID")]
    public virtual string GraphicTypeID
    {
        get;
        set;
    }
    [DataMember(Name = "GraphicSubTypeID")]
    public virtual string GraphicSubTypeID
    {
        get;
        set;
    }
    [DataMember(Name = "GraphicTypeTemplateID")]
    public virtual string GraphicTypeTemplateID
    {
        get;
        set;
    }
    [DataMember(Name = "TimeCodeIn")]
    public virtual string TimeCodeIn
    {
        get;
        set;
    }
    [DataMember(Name = "TimeCodeOut")]
    public virtual string TimeCodeOut
    {
        get;
        set;
    }
    [DataMember(Name = "AutoRetract")]
    public virtual bool AutoRetract
    {
        get;
        set;
    }
    [DataMember(Name = "Description")]
    public virtual string Description
    {
        get;
        set;
    }
    [DataMember(Name = "UserID")]
    public virtual int UserID
    {
        get;
        set;
    }

    [DataMember(Name = "GraphicDetails")]
    public GraphicDetailsCollection GraphicDetails
    {
        get;
        set;
    }

    [DataMember(Name = "OffsetX")]
    public virtual int OffsetX
    {
        get;
        set;
    }
    [DataMember(Name = "OffsetY")]
    public virtual int OffsetY
    {
        get;
        set;
    }
    [DataMember(Name = "OffsetZ")]
    public virtual int OffsetZ
    {
        get;
        set;
    }
}

如您所见,我有一个名为 GraphicDetailsCollection 的 CollectionDataContract,其结构如下所示:

[CollectionDataContract]
public class GraphicDetailsCollection : List<GraphicDetail>
{

}

集合本身非常简单,指的是DataContract:

[DataContract]
public class GraphicDetail
{
    [DataMember(IsRequired = false)]
    public string GraphicID;

    [DataMember(IsRequired = false)]
    public string PropName;

    [DataMember(IsRequired = false)]
    public string PropValue;

    [DataMember(IsRequired = false)]
    public string PropFileID;

    [DataMember(IsRequired = false)]
    public string PropFileDescription;
}

我有这个设置是因为 GraphicDetails 中可能有任意数量的 GraphicDetail 部分。除了 GraphicDetails 中的 GraphicDetail 内容外,我可以很好地处理 XML 中的所有数据。我遇到的问题是,当我引用contract.GraphicDetails.Count 以循环遍历各种GraphicDetail 集时,我看到contract.GraphicDetails.Count=0 并且所有这些都是DataMembers=Null,这是不正确的。

有人可以解释为什么会这样吗?我对 DataContracts 有点陌生,我觉得我要么非常接近,要么在没有完全理解 Collections 和 Contracts 的情况下陷入困境,需要一种不同的方法。

任何想法都会有所帮助,谢谢!

【问题讨论】:

    标签: c# asp.net xml datacontractserializer datacontract


    【解决方案1】:

    在显示的 XML 中,&lt;GraphicDetail&gt; 有一个 default namespace xmlns="http://schemas.datacontract.org/2004/07/fogREST"。因此,该元素及其所有子元素都在该名称空间中,只要它们缺少显式名称空间前缀(它们确实如此)。您的数据合同需要反映这一事实:

    [CollectionDataContract(Namespace = "http://schemas.datacontract.org/2004/07/fogREST")] // All GraphicDetail child XML elements are to be in the indicated namespace
    public class GraphicDetailsCollection : List<GraphicDetail>
    {
    }
    
    [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/fogREST")] // All data member child XML elements are to be in the indicated namespace
    public class GraphicDetail
    {
        [DataMember(IsRequired = false)]
        public string GraphicID;
    
        [DataMember(IsRequired = false)]
        public string PropName;
    
        [DataMember(IsRequired = false)]
        public string PropValue;
    
        [DataMember(IsRequired = false)]
        public string PropFileID;
    
        [DataMember(IsRequired = false)]
        public string PropFileDescription;
    }
    

    【讨论】:

    • 您好 dbc,首先,感谢您的帮助!我能够让它工作,但现在有一个问题,我有一个可能有也可能没有空值的 DataMember。在我当前的设置中,如果 PropFileID 没有值,DataContractSerializer 将返回一个字段 但我真正想要的是完全忽略(未生成)该元素。有没有办法做到这一点? EmitDefaultValue = false 似乎在正确的轨道上,但仅适用于序列化而不是反序列化。
    • @ChrisHarvey - DataMemberAttribute.EmitDefaultValue 应该可以工作。但是您写道,[it] 似乎走在正确的轨道上,但仅适用于序列化而不是反序列化。 在这种情况下,我建议用完整的minimal reproducible example 提出第二个问题,以显示什么是不工作。
    • 您好 dbc,我创建了一个新问题以进一步详细说明该问题。你介意检查一下吗? stackoverflow.com/questions/42800889/…
    猜你喜欢
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 2013-04-19
    • 2019-01-28
    • 2017-08-10
    • 2019-11-01
    相关资源
    最近更新 更多