Mr Big Spender
Mr Big Spender

Reputation: 29

Deserialize an XML string with WCF

I have a problem with deserialize an XML string into C# objects. The problem is that I the result will always be null. This is my XML string which is stored into a string variable.

<objects>
  <object>
    <dateadded>1614924419</dateadded>
    <id>CF7E7B22-1D3A-4CFE-91F9-F8C5C2DB4069</id>
    <name>NorthernLights</name>
    <parentid>ED98C97F-A202-48ED-AEEA-34362508A30B</parentid>
    <type>file</type>
  </object>
  <object>
    <dateadded>1614924419</dateadded>
    <id>CF7E7B22-1D3A-4CFE-91F9-F8C5C2DB4070</id>
    <name>Northern</name>
    <parentid>ED98C97F-A202-48ED-AEEA-34362508A30C</parentid>
    <type>file</type>
  </object>
</objects>

Those are the classes that I have created that represent the XML document. I suppose something is wrong there. Can someone help me with this?

This is the class for the objects tag:

namespace DataContractSample.DataContract.Model
{
    using System.Collections.Generic;
    using System.Runtime.Serialization;

    [DataContract(Name = "objects", Namespace = "", IsReference = false)]
    [KnownType(typeof(IList<Image>))]

    public class Images
    {
        [DataMember(Name = "object", EmitDefaultValue = false, IsRequired = true)]
        public IList<Image> ImageList;
    }
}

This is the class for the object tag:

namespace DataContractSample.DataContract.Model
{
    using System;
    using System.Runtime.Serialization;

    [DataContract(Name = "object", Namespace = "")]
    public class Image
    {
        [DataMember(Name = "Id")]
        public Guid id { get; set; }

        [DataMember(Name="parentid")]
        public Guid ParentId { get; set; }

        [DataMember(Name="name")]
        public string Name { get; set; }
        
        [DataMember(Name = "type")]
        public string Type { get; set; }

        [DataMember(Name = "dateadded")]
        public string DateAdded { get; set; }
    }
}

Thanks!

Upvotes: 0

Views: 241

Answers (1)

Peter Csala
Peter Csala

Reputation: 22839

The problem with your approach is that you want to deserialize the <objects> into a class and into a property at the same time. This won't work. Here, I present two different ways how you can solve this problem.

Option A

If you have an outer node around <objects>:

<?xml version="1.0" encoding="utf-8" ?>
<top>
  <objects>
    <object>
      <dateadded>1614924419</dateadded>
      <id>CF7E7B22-1D3A-4CFE-91F9-F8C5C2DB4069</id>
      <name>NorthernLights</name>
      <parentid>ED98C97F-A202-48ED-AEEA-34362508A30B</parentid>
      <type>file</type>
    </object>
    <object>
      <dateadded>1614924419</dateadded>
      <id>CF7E7B22-1D3A-4CFE-91F9-F8C5C2DB4070</id>
      <name>Northern</name>
      <parentid>ED98C97F-A202-48ED-AEEA-34362508A30C</parentid>
      <type>file</type>
    </object>
  </objects>
</top>

with this modified top level entity:

[DataContract(Name = "top", Namespace = "", IsReference = false)]
public class Images
{
    [DataMember(Name = "objects", EmitDefaultValue = false, IsRequired = true)]
    public List<Image> ImageList;
}

then deserialization works like a charm:

using var file = File.OpenRead("sample.xml");
using var reader = new XmlTextReader(file); 
var serializer = new DataContractSerializer(typeof(Images));
var data = (Images)serializer.ReadObject(reader);

Console.WriteLine(data.ImageList.Count); // Will print 2

Option B

If you don't have an outer node around <objects> then you can use CollectionDataContract:

[CollectionDataContract(Name = "objects", Namespace = "")]
public class Images: List<Image>
{

}

and it will work as well:

using var file = File.OpenRead("sample.xml");
using var reader = new XmlTextReader(file); 
var serializer = new DataContractSerializer(typeof(Images));
var data = (Images)serializer.ReadObject(reader);

Console.WriteLine(data.Count); // Will print 2

Upvotes: 1

Related Questions