我遇到了一个问题,我的对象没有从Post请求的主体反序列化,我跟着this answer表示因为WebApi默认使用DataContractSerializer,你需要定义xmlns
这样
<TestModel
xmlns="http://schemas.datacontract.org/2004/07/YourMvcApp.YourNameSpace">
确实有效,但如果我改变了年份或月份,如http://schemas.datacontract.org/2005/07/...
,它就会停止工作,我的对象再次变为空。
为什么这样,http://schemas.datacontract.org/2004/07/
以某种方式硬编码?为什么这个网址呢?
答案 0 :(得分:3)
每个数据合同对象都由完全限定数据合同名称标识。如Data Contract Names中所述:
有关命名数据合同的基本规则包括:
- 完全限定的数据协定名称由命名空间和名称组成。
- 数据成员只有名称,但没有名称空间。
- 处理数据合同时,WCF基础结构对名称空间以及数据合同和数据成员的名称都区分大小写。
数据协定命名空间采用统一资源标识符(URI)的形式。 URI可以是绝对的也可以是相对的。默认情况下,为特定类型的数据协定分配一个名称空间,该名称空间来自该类型的公共语言运行时(CLR)名称空间。
默认情况下,任何给定的CLR命名空间(格式为Clr.Namespace)都映射到命名空间&#34; http://schemas.datacontract.org/2004/07/Clr.Namespace&#34;。要覆盖此默认值,请将
ContractNamespaceAttribute
属性应用于整个模块或程序集。或者,要控制每种类型的数据协定命名空间,请设置Namespace
的DataContractAttribute
属性。
要使数据合同等效,它们必须具有相同的命名空间和名称。此外,一方的每个数据成员必须在另一方具有等效的数据成员。
因此,要通过网络成功发送数据合同对象,完全限定的数据协定名称必须在两端匹配。如上所述,默认数据协定命名空间为http://schemas.datacontract.org/2004/07/Clr.Namespace
,但您可能希望更改此设置以反映您的组织,例如:
[DataContract(Namespace = "http://schemas.MyOrganization.com/v1")]
public class TestModel
{
[DataMember]
public string Value { get; set; }
}
或者您可以为整个程序集和.Net命名空间设置它:
[assembly: ContractNamespace("http://schemas.MyOrganization.com/v1", ClrNamespace = "YourMvcApp.YourNameSpace")]
数据协定序列化可以用于JSON和XML,那么DataContractSerializer
如何将数据协定名称映射到XML?它使用XML元素本地名称和名称空间URI来实现:
<TestModel xmlns="http://schemas.datacontract.org/2004/07/YourMvcApp.YourNameSpace">
xmlns="http://schemas.datacontract.org/2004/07/YourMvcApp.YourNameSpace"
属性是具有本地名称TestModel
的元素的default XML namespace declaration。本地名称和命名空间一起构成元素的expanded name。如果名称空间URI和本地名称匹配,则XML元素名称被认为是相等的,因此Microsoft选择将数据协定名称与XML元素本地名称对应,并将数据协定名称空间与XML名称空间URI相对应,这就是更改甚至URI中的年份或月份会导致反序列化失败。
因此,正如您所看到的,在推出数据协定Web API或WCF服务之前,需要先确定命名空间的选择,因为更改命名空间需要更新客户端上的命名空间。 (当然,对于WCF,客户端通常会根据解释的模式元数据自动生成客户端,例如here或here。)