I needed to have a Web API service with some fake data for a new PoC. The objectmodel for this is quite simple, 2 classes, where class1 has a nested array of class2. So I started building a FakeDataService where I just hardcoded some data. For brevity in this sample, I have omitted a lot of properties so the code focuses on the essence of the problem:
public class Class1
{
public string Prop1 { get; set; }
public IEnumerable<Class2> Prop2 { get; set; }
public IEnumerable<string> Prop3 { get; set; }
}
public class Class2
{
public string Prop4 { get; set; }
}
public static class FakeDatabase
{
public static Class1 c1instance1 = new Class1 { Prop1 = "value1",
Prop2 = new Class2[] { c2instance1 },
Prop3 = new string[] { "value3" } };
public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" };
public static Class1[] AllData = new Class1[] { c1instance1 };
}
So, my "AllData" of the fake database is an array of Class1 objects ("array" of just one in this example), and Class1 objects have a string property (prop1), an array of Class2 objects (prop2), and an array of strings property (prop3), while Class2 objects just have one string property (prop4).
The WebAPI controller is as basic as it gets:
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<Class1> Get()
{
return FakeDatabase.AllData;
}
But when I invoke the Values controller, the result is :
<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2 i:nil="true"/>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>
Notice how the serialization of the Class2 object yields i:nil=true
After a good few hours of searching (My example data was a LOT bigger than this simple sample here), I found that the root of the problem was the fact that the array of nested objects are defined as static instances. Eg. Change the initial code of FakeDatabase to :
public static class FakeDatabase
{
public static Class1 c1instance1 = new Class1 { Prop1 = "value1",
Prop2 = new Class2[] { new Class2 { Prop4 = "Value4" }},
Prop3 = new string[] { "value3" } };
public static Class1[] AllData = new Class1[] { c1instance1 };
}
Invoking the WebAPI controller now gives me (correctly) :
<ArrayOfClass1 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FakeDataService.Models">
<Class1>
<Prop1>value1</Prop1>
<Prop2>
<Class2>
<Prop4>Value4</Prop4>
</Class2>
</Prop2>
<Prop3 xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d3p1:string>value3</d3p1:string>
</Prop3>
</Class1>
</ArrayOfClass1>
So the only difference is the array of Class2 objects. What could be the explanation of this behavior ?