我有一个可序列化的多态类型和服务合同。
[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
{ }
[ServiceContract]
[ServiceKnownType(typeof(SomethingA))]
[ServiceKnownType(typeof(SomethingB))]
public interface ITesting
{
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-something",
Method = "POST")]
Something UseSomething();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "use-polymorphic-somethings",
Method = "POST")]
List<Something> UsePolymorphicSomethings();
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "throw-web-exception",
Method = "POST")]
void ThrowServerException();
}
......以及该合同的实施。
using System.Net;
using System.ServiceModel.Web;
public class Testing : ITesting
{
public Something UseSomething()
{
SomethingA a = new SomethingA();
a.Item1 = 2;
a.Item2 = "b";
return a;
}
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;
}
public void ThrowServerException()
{
try
{
throw new ApplicationException("Bad news.");
}
catch (ApplicationException e)
{
throw new WebFaultException<ApplicationException>(e, HttpStatusCode.InternalServerError);
}
}
}
我在另一个程序集中有一些功能测试。
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
[TestMethod]
public void UseSomething_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-something",
new StringContent(string.Empty)).Result;
string ret1 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA as Something.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Something));
Something ret = (Something)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(SomethingA), ret.GetType());
}
}
[TestMethod]
public void UsePolymorphicSomethings_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsJsonAsync("use-polymorphic-somethings",
new StringContent(string.Empty)).Result;
string ret2 = response.Content.ReadAsStringAsync().Result;
// Deserializes SomethingA and SomethingB correctly.
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());
}
}
[TestMethod]
public void ThrowServerException1_WebTest()
{
using (HttpClient http = new HttpClient())
{
http.BaseAddress = TestUtil.TestsBaseAddress;
HttpResponseMessage response = http.PostAsync("throw-web-exception",
new StringContent(string.Empty)).Result;
Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode);
string ret3 = response.Content.ReadAsStringAsync().Result;
// Deserializes ApplicationException as Exception.
Stream stream = response.Content.ReadAsStreamAsync().Result;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Exception));
Exception e = (Exception)serializer.ReadObject(stream);
// FAILS.
Assert.AreEqual(typeof(ApplicationException), e.GetType());
}
}
在UseSomething_WebTest中,ret1为:
"{\"Item1\":2,\"Item2\":\"b\"}"
...没有嵌入类型信息,不出所料,DataContractJsonSerializer无法反序列化返回的对象的正确类型。
In UsePolymorphicSomethings_WebTest ret2是:
"[{\"__type\":\"SomethingA:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"},{\"__type\":\"SomethingB:#InSite8WebServiceLib\",\"Item1\":1,\"Item2\":\"1\"}]"
...以__type条目的形式嵌入的类型信息,DataContractJsonSerializer正确地反序列化。
在ThrowServerException1_WebTest中,ret3是:
"{\"ClassName\":\"System.ApplicationException\",\"Message\":\"Bad news.\",\"Data\":null,\"InnerException\":null,\"HelpURL\":null,\"StackTraceString\":\" at InSite8WebServiceLib.Testing.ThrowServerException() in d:\\\\SvnSource\\\\Hammersmith\\\\trunk\\\\VisualStudioProjects\\\\InSite8WebService\\\\InSite8WebServiceLib\\\\Testing\\\\Testing.cs:line 74\",\"RemoteStackTraceString\":null,\"RemoteStackIndex\":0,\"ExceptionMethod\":\"8\\u000aThrowServerException\\u000aInSite8WebServiceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\\u000aInSite8WebServiceLib.Testing\\u000aVoid ThrowServerException()\",\"HResult\":-2146232832,\"Source\":\"InSite8WebServiceLib\",\"WatsonBuckets\":null}"
...以ClassName条目的形式嵌入类型信息,DataContractJsonSerializer无法正确反序列化。
所以我的问题是这个。为什么对于单个WCF WebHttp端点,多个WebInvoke属性方法返回几种不同格式的JSON,其中只有一个DataContractJsonSerializer可以实际反序列化,以及如何修复它以使其正常工作?
答案 0 :(得分:0)
您可以通过重载构造函数来强制DataContractJsonSerializer始终发出类型信息。然后将 alwaysEmitTypeInformation 参数设置为True。
有关MSDN
的更多信息