Search code examples
c#arraysrestdatacontractteamcity-8.0

DataContract and Arrays in Top Level elements


I have an xml file coming down from TeamCity that looks like this (no other elements):

<builds count="2">
    <build id="1" number="100" running="true" (etc) />
    <build id="2" number="200" running="true" (etc) />
    <build id="3" number="200" running="true" (etc) />
</builds>

My data contracts look like this:

[Serializable,DataContract(Name="builds", Namespace = "")]
    public class builds
    {
        [XmlArray]
        public build[] build;

        [XmlAttribute("count")] 
        public int count { get; set; }

    }

    [Serializable, DataContract(Name = "build", Namespace = "")]
    public class build
    {
        [XmlAttribute("id")]
        public int id;

        [XmlAttribute("number")]
        public int number;

        [XmlAttribute("running")]
        public bool running;

        [XmlAttribute("percentageComplete")]
        public int percentageComplete;

        [XmlAttribute("status")]
        public string status;

        [XmlAttribute("buildTypeId")]
        public string buildTypeId;

        [XmlAttribute("startDate")]
        public string startDate;

        [XmlAttribute("href")]
        public string href;

        [XmlAttribute("webUrl")]
        public string webUrl;
    }

Clearly I wouldn't be here if that was working :) How do I fix an issue with serialization of top level array elements that are all named the same? If I make it into a single instance of build it works fine and I can interact with the object.


Solution

  • What about following

        [Fact]
        public void Test()
        {
            var builds = new builds
                {
                    build = new[]
                        {
                            new build
                                {
                                    buildTypeId = "1",
                                    number = 100,
                                    running = true
                                },
                            new build
                                {
                                    buildTypeId = "2",
                                    number = 200,
                                    running = true
                                }
                        }
                };
    
            var namespaces = new XmlSerializerNamespaces();
            namespaces.Add(string.Empty, string.Empty);
            var writer = new StringWriter();
            new XmlSerializer(typeof(builds)).Serialize(writer, builds, namespaces);
            string result = writer.ToString();
            Console.Write(result);
        }
    
        [XmlRoot("builds")]
        public class builds
        {
            [XmlElement("build")]
            public build[] build;
    
            [XmlAttribute("count")]
            public int count { get; set; }
        }
    
        public class build
        {
            [XmlAttribute("buildTypeId")]
            public string buildTypeId;
    
            [XmlAttribute("href")]
            public string href;
    
            [XmlAttribute("id")]
            public int id;
    
            [XmlAttribute("number")]
            public int number;
    
            [XmlAttribute("percentageComplete")]
            public int percentageComplete;
    
            [XmlAttribute("running")]
            public bool running;
    
            [XmlAttribute("startDate")]
            public string startDate;
    
            [XmlAttribute("status")]
            public string status;
    
            [XmlAttribute("webUrl")]
            public string webUrl;
        }
    

    Result output:

    <?xml version="1.0" encoding="utf-16"?>
    <builds count="0">
      <build buildTypeId="1" id="0" number="100" percentageComplete="0" running="true" />
      <build buildTypeId="2" id="0" number="200" percentageComplete="0" running="true" />
    </builds>