Пользовательский объект WCF возвращает корректно, кроме возврата пустых списков

#wcf #xml-serialization

#wcf #xml-сериализация

Вопрос:

Я отправляю XML на свой веб-сервис, и метод получения:

 public XElement SubmitRecipe(Recipe recipe)
  

Параметр recipe правильно получает все свойства, кроме recipe.Количество аллергий равно 0, кто-нибудь знает почему?

Пример XML-файла:

 <Recipe>
<Allergies>
    <Allergy>nuts</Allergy>
    <Allergy>wheat</Allergy>
</Allergies>
<Title>recipe title</Title>
<Id>107</Id>
</Recipe
  

Объект Recipe:

 [CollectionDataContract(Name = "Allergies", ItemName = "Allergy")]
public class AllergyList : List<string> { }

[DataContract]
public class Recipe
{        
    [DataMember(Name = "Allergies")]
    public AllergyList Allergies { get; set; }

    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Title { get; set; }
}
  

В моем тесте create method я получаю то, что ожидаю:

 public Recipe GetRecipe()
{
    Recipe recipe = new Recipe();

    recipe.Id = 1;
    recipe.Allergies = new AllergyList();
    recipe.Allergies.Add("nuts");
    recipe.Allergies.Add("wheat");
}

<Recipe>
    <Allergies>
        <a:Allergy>nuts</a:Allergy>
        <a:Allergy>wheat</a:Allergy>
    </Allergies>
    <Id>1</Id>
</Recipe>
  

Ответ №1:

Возможно, у вас есть пространство имен XML (не .NET namespace) проблема с вашими сервисными контрактами. Показанный вами тестовый пример содержит элемент «a: Allery» для ссылки на элементы коллекции. В то время как образец XML не содержит псевдоним пространства имен XML «a:». Я почти всегда устанавливаю пространство имен для всех контрактов на обслуживание, операции и данные. Да, это может быть утомительно, но выигрыш в том, что у вас не возникнет проблем с пространством имен XML, и это определенно поможет с управлением версиями контрактов данных в будущем. Вот как будет выглядеть ваш контракт:

 [CollectionDataContract(Name = "Allergies", ItemName = "Allergy",
    Namespace="http://yourorg.co.uk/2011/05/Medical")]
public class AllergyList : List<string> { }

[DataContract(Namespace="http://yourorg.co.uk/2011/05/Medical")]
public class Recipe
{        
    [DataMember(Name = "Allergies")]
    public AllergyList Allergies { get; set; }

    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Title { get; set; }
}
  

Ответ №2:

Проверьте, что происходит с помощью Fiddler (или чего-то подобного) и сравните, создав экземпляры ваших типов и сериализуя их в файл (например) с помощью DataContractSerializer (пример здесь).). Вывод файла покажет, что ожидает сериализатор, и вы сможете увидеть любые различия с тем, что отправляет ваш клиент, с тем, что было зарегистрировано в Fiddler — например, различия в пространстве имен

Другой вариант — использовать другой клиент, где вы можете вручную установить XML (например, SoapUI).