我在http://localhost:8090/api/Test有一个WCF端点。实现看起来有点像这样:
[OperationContract]
[WebInvoke(
Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "Test")]
void TestEndpoint(Test test);
我有一些在其他地方声明的数据对象
[DataContract]
public class TestBase
{
[DataMember(Name = "BaseValue")]
public string BaseValue { get; set; }
}
[DataContract(Namespace = "")]
public class Test : TestBase
{
[DataMember(Name = "TestValue")]
public string TestValue { get; set; }
}
我遇到的问题是当我调用端点并通过请求体传递对象数据时,数据只在我使用JSON时被正确序列化,而不是在我使用XML时。
以下内容非常棒。 Test.TestValue ==“TestValue”和Test.BaseValue ==“BaseValue”。
POST http://localhost:8090/api/Test
Content-Type: text/json
{ "TestValue":"Test", "BaseValue": "BaseValue" }
当我执行以下Test.TestValue ==“TestValue”和Test.BaseValue == null:(
POST http://localhost:8090/api/Test
Content-Type: text/xml
<Test> <TestValue>Test</TestValue> <BaseValue>Base</BaseValue></Test>
关于我在这里做错了什么的想法?
答案 0 :(得分:1)
首先,您需要将基类放在与派生类相同的名称空间中:
[DataContract(Namespace = "")]
public class TestBase
{
[DataMember(Name = "BaseValue")]
public string BaseValue { get; set; }
}
如果不这样做,BaseValue
实际上将位于不同的命名空间中,即数据协定序列化程序选择的默认命名空间:
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<BaseValue xmlns="http://schemas.datacontract.org/2004/07/ClrNamespace">foo</BaseValue>
<TestValue>bar</TestValue>
</Test>
(JSON没有对象名称空间,所以这不是问题。)
接下来,BaseValue
必须在XML中TestValue
之前,因为data contract serializer对订单敏感。见Data Member Order:
数据排序的基本规则包括:
如果数据协定类型是继承层次结构的一部分,则其基本类型的数据成员始终位于订单中。
接下来依次是当前类型的数据成员,它们没有按字母顺序设置DataMemberAttribute属性的Order属性。
接下来是具有DataMemberAttribute属性集的Order属性的任何数据成员。它们首先按Order属性的值排序,然后按字母顺序排序,如果某个Order值有多个成员。可以跳过订单值。
通过调用CompareOrdinal方法建立字母顺序。
(相反,JSON对象属性定义为unordered,因此您不会遇到DataContractJsonSerializer
的这种复杂情况。)
因此,在基类上添加了名称空间声明后,可以反序列化以下XML:
<Test> <BaseValue>Base</BaseValue> <TestValue>Test</TestValue> </Test>