WCF Json反序列化。WCF Json反序列化保存多態集合類型
我正在WCF中使用Dotnet 4.5構建一箇中間件webservice,該服務器返回一個多態類型。
[DataContract]
[KnownType(typeof(SomethingA))]
[KnownType(typeof(SomethingB))]
public class Something
{
[DataMember]
public int Item1 { get; set; }
[DataMember]
public string Item2 { get; set; }
}
[DataContract]
public class SomethingA : Something
{ }
[DataContract]
public class SomethingB : Something
{ }
/// <summary>
/// Contract for a service for testing various web operations.
/// </summary>
[ServiceContract]
[ServiceKnownType(typeof(SomethingA))]
[ServiceKnownType(typeof(SomethingB))]
public interface ITesting
{
/// <summary>
/// Test passing in and returning an object using POST and json.
/// </summary>
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-polymorphic-somethings",
Method = "POST")]
List<Something> UsePolymorphicSomethings();
}
/// <summary>
/// Implementation of the ITesting service contract.
/// </summary>
public class Testing : ITesting
{
public List<Something> UsePolymorphicSomethings()
{
List<Something> retVal = new List<Something>();
retVal.Add(new SomethingA { Item1 = 1, Item2 = "1" });
retVal.Add(new SomethingB { Item1 = 1, Item2 = "1" });
return retVal;
}
}
在客戶端,我試圖反序列化這種方式來保存集合中的不同類型。 MSDN文檔對我來說似乎非常薄弱。我遇到的第一個問題是添加一個對System.Web.Http的引用,在第三方開源組件Newtonsoft.Json上創建了一個未公開的動態依賴關係,我必須從Web上下載它。
前兩種反序列化方法失敗,但我發現了第三種方法。
我想知道的是爲什麼前兩種方法失敗?理想情況下,我希望得到第一種工作方式,因爲這是最簡化的。
[TestMethod]
public void UsePolymorphicSomethings_Test1()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = new Uri("http://localhost:8733/");
HttpResponseMessage response = http.PostAsJsonAsync(
"Design_Time_Addresses/InSite8WebServiceLib2/Testing/use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
List<Something> ret = response.Content.ReadAsAsync<List<Something>>().Result;
// FAILS.
Assert.AreEqual(typeof(SomethingA), somethings[0].GetType());
Assert.AreEqual(typeof(SomethingB), somethings[1].GetType());
}
}
[TestMethod]
public void UsePolymorphicSomethings_Test2()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = new Uri("http://localhost:8733/");
HttpResponseMessage response = http.PostAsJsonAsync(
"Design_Time_Addresses/InSite8WebServiceLib2/Testing/use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
string ret1 = response.Content.ReadAsStringAsync().Result;
Newtonsoft.Json.JsonSerializerSettings s = new Newtonsoft.Json.JsonSerializerSettings();
s.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;
List<Something> r = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Something>>(ret1, s);
// FAILS.
Assert.AreEqual(typeof(SomethingA), somethings[0].GetType());
Assert.AreEqual(typeof(SomethingB), somethings[1].GetType());
}
}
[TestMethod]
public void UsePolymorphicSomethings_Test3()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = new Uri("http://localhost:8733/");
HttpResponseMessage response = http.PostAsJsonAsync(
"Design_Time_Addresses/InSite8WebServiceLib2/Testing/use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Something>));
List<Something> somethings = (List<Something>)serializer.ReadObject(stream);
// SUCCEEDS.
Assert.AreEqual(typeof(SomethingA), somethings[0].GetType());
Assert.AreEqual(typeof(SomethingB), somethings[1].GetType());
}
}
嗨,我相信最後一種方法工作的原因,其他兩個沒有。是因爲當您使用WebMessageFormat.Json時,使用服務器端的序列化程序是DataContractJsonSerializer。所以使用相同的串行器服務器和客戶端都是有道理的,最終會取得令人滿意的結果。例如,如果你想使用NewstonSoft,你必須側身,創建一個消息格式化類,一個Web http行爲,一個行爲擴展元素和一個web內容類型映射器,然後你需要把所有這些都綁定起來,可能是網頁或應用程序配置文件。 – 2014-11-04 05:56:07
我明白了。在這種情況下,UsePolymorphicSomethings_Test1必須使用不同的具有JSON能力的反序列化器(因爲它確實執行反序列化,只是不正確),這引發了幾個問題。哪個JSON序列化程序默認使用ReadAsAsync?爲什麼它默認不使用DataContractJsonSerializer?並且可以將ReadAsAsync配置爲默認使用DataContractJsonSerializer,因爲它的默認配置是無用的? – Neutrino 2014-11-07 13:33:57
如果我不必使用Newtonsoft,我真的不想使用Newtonsoft,我嘗試使用Newtonsoft類反序列化的唯一原因是因爲我的集成測試程序集中的System.Net.Http創建了一個動態(運行時)對它的依賴這讓我猜想它可能以某種方式與這個問題有關。 – Neutrino 2014-11-07 13:34:26