2015-07-03 8 views
1

Мне нужно было иметь службу веб-API с некоторыми поддельными данными для нового PoC. Объектная модель для этого довольно проста, 2 класса, где class1 имеет вложенный массив класса2. Итак, я начал создавать FakeDataService, где я просто закодировал некоторые данные. Для краткости в данном примере я опустил много свойств, поэтому код фокусируется на сути проблемы:WebAPI 2 JSON Сериализация объектных массивов с вложенными экземплярами статических объектов завершена

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

} 

Итак, мой «AllData» поддельных баз данных является массивом объектов class1 (» массив "только одного в этом примере), а объекты Class1 имеют свойство string (prop1), массив объектов Class2 (prop2) и массив свойств строк (prop3), в то время как объекты Class2 имеют только одно свойство строки (prop4).

Контроллер WebAPI как основной, как он получает:

public class ValuesController : ApiController 
{ 

    // GET api/values 
    public IEnumerable<Class1> Get() 
    { 
     return FakeDatabase.AllData;                                              
    } 

Но когда я призываю контроллер Values, результат:

Обратите внимание, как сериализация доходности объекта Class2 я : nil = true

После нескольких часов поиска (мои данные примера были LOT больше, чем этот простой образец здесь), я обнаружил, что корень проблемы был фактом tha t массив вложенных объектов определяется как статические экземпляры. Например. Измените исходный код FakeDatabase к:

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

} 

Вызов контроллера WebAPI теперь дает мне (правильно):

<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> 

Таким образом, единственное отличие заключается в массив объектов class2. Что может быть объяснением этого поведения?

+0

Ваш вывод XML, поэтому вы не используете Json.NET здесь, вы, вероятно, используете 'DataContractSerializer'. Но на самом деле проблема не связана с конкретным сериализатором. Я обновил теги, чтобы это отразить. – dbc

ответ

0

Ваша проблема в том, что вы статическую переменную c2instance1 перед ее инициализацией. Из C# Language Specification §10.4.5.1 Static field initialization:

статическое поле инициализаторы переменных одного класса соответствуют последовательности заданий, которые выполняются в текстовом порядке , в котором они появляются в объявлении класса.

Таким образом, в вашем FateDatabase классе, c1instance1 используется инициализаторе c1instance1, пока еще нулевой:

public static class FakeDatabase 
{ 
    public static Class1 c1instance1 = new Class1 
    { 
     Prop1 = "value1", 
     Prop2 = new Class2[] { c2instance1 }, // NOT INITIALIZED YET, THUS NULL 
     Prop3 = new string[] { "value3" } 
    }; 

    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" }; 

    public static Class1[] AllData = new Class1[] { c1instance1 }; 
} 

Флип текстуальное порядок статических переменных, чтобы исправить ошибку:

public static class FakeDatabase 
{ 
    public static Class2 c2instance1 = new Class2 { Prop4 = "Value4" }; 

    public static Class1 c1instance1 = new Class1 
    { 
     Prop1 = "value1", 
     Prop2 = new Class2[] { c2instance1 }, 
     Prop3 = new string[] { "value3" } 
    }; 

    public static Class1[] AllData = new Class1[] { c1instance1 }; 
} 
+0

Спасибо! Это и есть причина. Ps, служба вернула JSOn, но я еще не изменил Content-Type по умолчанию, поэтому Chrome отобразил его как XML. – hcd