Search code examples
c#asp.netxmldatacontractserializerdatacontract

CollectionDataContract not recognizing DataContract


I am trying to consume XML from a WebInvoke POST call. The main class that reflects the XML structure and the XML itself are as follows:

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:

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

As you can see I have a CollectionDataContract called GraphicDetailsCollection that is structured as you see below:

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

}

The collection itself is very straightforward and refers to the 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;
}

I have this setup because there can be potentially any number of GraphicDetail sections within GraphicDetails. I can handle all of the data within the XML fine except for the GraphicDetail content in GraphicDetails. The problem I have is that when I make references to contract.GraphicDetails.Count in order to loop through the various sets of GraphicDetail, I see that contract.GraphicDetails.Count=0 and all of it's DataMembers=Null which isn't true.

Can someone explain why this might be? I am somewhat new to DataContracts and I feel like I am either very close or have worked myself into a corner without fully understanding Collections and Contracts and need a different approach.

Any thoughts would be helpful, thanks!


Solution

  • In the XML shown, the <GraphicDetail> has a default namespace xmlns="http://schemas.datacontract.org/2004/07/fogREST". Thus that element and all its child elements are in that namespace as long as they lack an explicit namespace prefix (which they do). Your data contracts need to reflect that fact:

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