2011-04-24 163 views
6

我無法反序列化我的WCF Web服務的結果。該方法返回一個List<RecipeEntity>,它被序列化爲XML,如下所示。當我嘗試反序列化時,我只是得到一個異常,如下所示。看來我無法反序列化<ArrayOfRecipe>List<RecipeEntity>。請注意0​​由合同名稱映射到Recipe將XML反序列化爲<ArrayOf>以列表<>

搜索後,我看到很多人提出了XmlArray和XmlElement屬性,但據我所知他們不適用於GetRecipes()方法。我只看到它們用在序列化類的字段上。

我知道我可以將List<RecipeEntity>包裝在RecipeList類中,然後返回,但是我寧願直接反序列化到列表<>以獲得任何給定的類型。

例外:

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

回答

8

您正在使用DataContractSerializer序列化和XmlSerializer反序列化。這兩個不使用相同的方法。您必須在您的反序列化方法中使用DataContractSerializer,或者您必須使用XmlSerializerFormat屬性標記您的操作或服務(在這種情況下,WCF將使用XmlSerializer而不是DataContractSerializer)。 DataContractDataMember屬性僅適用於DataContractSerializerXmlSerializer使用其在System.Xml.Serialization名稱空間中定義的屬性。

2

只需首先獲取響應流,然後使用DataContractSerealizer去實現它。

DeSerealization代碼:

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