Десериализовать <ArrayOf>в XML в список <> - PullRequest
6 голосов
/ 25 апреля 2011

У меня проблемы с десериализацией результата из моего веб-сервиса WCF.Метод возвращает List<RecipeEntity>, который сериализуется в XML, как показано ниже.Когда я пытаюсь десериализовать, я просто получаю исключение, показанное ниже.Кажется, я не могу десериализовать <ArrayOfRecipe> до List<RecipeEntity>.Обратите внимание, что RecipeEntity сопоставляется по имени контракта с Recipe.

. После поиска я вижу много предлагаемых атрибутов XmlArray и XmlElement, но, насколько я могу судить, они не применяются здесь к методу GetRecipes(),Я видел только их использование в полях сериализованных классов.

Я знаю, что мог бы обернуть List<RecipeEntity> в класс RecipeList и вернуть его вместо этого, но я бы предпочел десериализовать непосредственно в List <> для любогозаданный тип.

Исключение:

System.InvalidOperationException was caught
  Message=There is an error in XML document (1, 2).
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
       at GroceriesAppSL.Pages.Home.GetRecipesCallback(RestResponse response)
  InnerException: System.InvalidOperationException
       Message=<ArrayOfRecipe xmlns='Groceries.Entities'> was not expected.
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read5_Recipe()
       InnerException: 

Контракт данных:

[DataContract(Name = "Recipe", Namespace = "Groceries.Entities")]
public class RecipeEntity
{
    [DataMember] public int Id;
    [DataMember] public string Name;
    [DataMember] public string Description;
}

Реализация:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "Recipes/{username}")]
    List<RecipeEntity> GetRecipes(string username);
}

public class MyService : IMyService
{
    public List<RecipeEntity> GetRecipes(string username)
    {
        return _recipeDB.Recipes.Select(ToEntity).ToList();
    }
}

Пример XML-результата, для иллюстрациитолько.

<ArrayOfRecipe xmlns="Groceries.Entities" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Recipe>
<Id>139</Id>
<Name>ExampleRecipe</Name>
<Description>5 L milk;4 eggs</Description>
</Recipe>
<Recipe>...</Recipe>
<Recipe>...</Recipe>
<Recipe>...</Recipe>
...
</ArrayOfRecipe>

Код десериализации:

using (var xmlReader = XmlReader.Create(new StringReader(response.Content)))
{
    var xs = new System.Xml.Serialization.XmlSerializer(typeof(List<RecipeEntity>));
    var recipes = (List<RecipeEntity>)xs.Deserialize(xmlReader);
}

Ответы [ 2 ]

9 голосов
/ 25 апреля 2011

Вы используете DataContractSerializer для сериализации и XmlSerializer для десериализации. Эти двое не используют один и тот же подход. Вы должны либо использовать DataContractSerializer в своем методе десериализации, либо пометить свою операцию или службу атрибутом XmlSerializerFormat (в этом случае WCF будет использовать XmlSerializer вместо DataContractSerializer). Атрибуты DataContract и DataMember предназначены только для DataContractSerializer. XmlSerializer использует свои собственные атрибуты, определенные в System.Xml.Serialization пространстве имен.

2 голосов
/ 28 июня 2014

Просто сначала вы получаете поток ответов, а затем используете DataContractSerealizer для его десертилизации.

Код десереализации:

using(Stream answer=webResponse.GetResponseStream())
    {
     DataContractSerializer xmlSer = new DataContractSerializer(typeof(RecipeEntity[]));
     var RecipeList = (RecipeEntity[])xmlSer.ReadObject(answer);
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...