DataContractSerializer是否仅适用于http://schemas.datacontract.org/2004/07/

时间:2017-03-27 16:29:30

标签: c# xml asp.net-web-api datacontractserializer

我遇到了一个问题,我的对象没有从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/以某种方式硬编码?为什么这个网址呢?

1 个答案:

答案 0 :(得分:3)

每个数据合同对象都由完全限定数据合同名称标识。如Data Contract Names中所述:

  

有关命名数据合同的基本规则包括:

     
      
  • 完全限定的数据协定名称由命名空间和名称组成。
  •   
  • 数据成员只有名称,但没有名称空间。
  •   
  • 处理数据合同时,WCF基础结构对名称空间以及数据合同和数据成员的名称都区分大小写。
  •   
     

数据协定命名空间采用统一资源标识符(URI)的形式。 URI可以是绝对的也可以是相对的。默认情况下,为特定类型的数据协定分配一个名称空间,该名称空间来自该类型的公共语言运行时(CLR)名称空间。

     

默认情况下,任何给定的CLR命名空间(格式为Clr.Namespace)都映射到命名空间&#34; http://schemas.datacontract.org/2004/07/Clr.Namespace&#34;。要覆盖此默认值,请将ContractNamespaceAttribute属性应用于整个模块或程序集。或者,要控制每种类型的数据协定命名空间,请设置NamespaceDataContractAttribute属性。

Data Contract Equivalence

  

要使数据合同等效,它们必须具有相同的命名空间和名称。此外,一方的每个数据成员必须在另一方具有等效的数据成员。

因此,要通过网络成功发送数据合同对象,完全限定的数据协定名称必须在两端匹配。如上所述,默认数据协定命名空间为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,客户端通常会根据解释的模式元数据自动生成客户端,例如herehere。)