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