DataContractSerializer的输出在.NET和Mono之间有所不同

时间:2013-03-06 08:03:55

标签: c# .net mono xamarin.android

我在Mono For Android应用程序中序列化数据,并使用REST将其发送到使用WCF监听的.NET服务器。到目前为止,这已经很好,但是,对于这个特定的数据合同,虽然服务器没有抛出任何错误,但数据合同中的列表显示为空。

使用Fiddler并使用相同的代码创建两个项目,我能够将正常的.NET DataContractSerializer输出与Mono的DataContractSerializer实现的输出进行比较。

.NET输出:

<VisitDataContractEx xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts">
  <_isDirty xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">true</_isDirty>
  <_id xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.Domain" xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:internalValue>a7b97b48-d3a9-419d-9f4e-330ffc7a01ee</d2p1:internalValue>
  </_id>
  <_key xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">false</_key>
  <_keyIdentifier xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">SurrogateKey</_keyIdentifier>
  <ChecklistComplete>false</ChecklistComplete>
  <Date>2013-03-05T15:43:49.5008406+02:00</Date>
  <GpsAccuracy>1</GpsAccuracy>
  <GpsLatitude>1</GpsLatitude>
  <GpsLongitude>1</GpsLongitude>
  <OrderComplete>false</OrderComplete>
  <PhotoComplete>false</PhotoComplete>
  <StockComplete>false</StockComplete>
  <Sync>2013-03-05T15:43:49.5468406+02:00</Sync>
  <checkListAnswers xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>
        <d2p1:_dataContract z:Id="i2">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>95ae919b-a389-4ea7-a009-af1b91890c36</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Answer>false</Answer>
          <checkListQuestion>
            <d2p1:_dataContract i:nil="true" />
            <d2p1:_description i:nil="true" />
            <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
            <d2p1:_id xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
              <d7p1:internalValue>176cbb31-7df2-4966-baa9-4e3cd2a0c6d5</d7p1:internalValue>
            </d2p1:_id>
          </checkListQuestion>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>95ae919b-a389-4ea7-a009-af1b91890c36</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>
    </d2p1:_list>
  </checkListAnswers>
  <comments xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list />
  </comments>
  <directSalesAgent xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>6f99f86a-5b1b-4f73-bdc3-388e0b7cf417</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgent>
  <directSalesAgentSuperVisor xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>d57db20d-9b3a-4345-849e-d5a0d0d88f70</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgentSuperVisor>
  <photos xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfPhotoDataContractExX8I0_S_SPU>
        <d2p1:_dataContract z:Id="i3">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>3db431e9-3338-4c96-aea9-d833eb0dc8ae</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Content i:nil="true" />
          <Taken>2013-03-05T15:43:49.4748406+02:00</Taken>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>3db431e9-3338-4c96-aea9-d833eb0dc8ae</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfPhotoDataContractExX8I0_S_SPU>
    </d2p1:_list>
  </photos>
  <salesPoint xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>692a294a-2d1b-4026-9693-0c0ce552a2fb</d3p1:internalValue>
    </d2p1:_id>
  </salesPoint>
  <stockCounts xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts" i:nil="true" />
</VisitDataContractEx>

单声道输出:

<VisitDataContractEx xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts">
  <_isDirty xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">true</_isDirty>
  <_id xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.Domain" xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:internalValue>9297eea9-82af-4981-ab9d-40aa0ac0fa0d</d2p1:internalValue>
  </_id>
  <_key xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">false</_key>
  <_keyIdentifier xmlns="http://schemas.datacontract.org/2004/07/Organization.DataContracts">SurrogateKey</_keyIdentifier>
  <ChecklistComplete>false</ChecklistComplete>
  <Date>2013-03-05T17:49:06.362243+02:00</Date>
  <GpsAccuracy>1</GpsAccuracy>
  <GpsLatitude>1</GpsLatitude>
  <GpsLongitude>1</GpsLongitude>
  <OrderComplete>false</OrderComplete>
  <PhotoComplete>false</PhotoComplete>
  <StockComplete>false</StockComplete>
  <Sync>2013-03-05T17:49:06.438934+02:00</Sync>
  <checkListAnswers xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>
        <d2p1:_dataContract xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" z:Id="i2">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>75083457-9714-4971-b60c-f28fa43167ad</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Answer>false</Answer>
          <checkListQuestion xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
            <d6p1:_dataContract xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
            <d6p1:_description i:nil="true" />
            <d6p1:_hasDataContract>false</d6p1:_hasDataContract>
            <d6p1:_id xmlns:d7p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
              <d7p1:internalValue>176cbb31-7df2-4966-baa9-4e3cd2a0c6d5</d7p1:internalValue>
            </d6p1:_id>
          </checkListQuestion>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>75083457-9714-4971-b60c-f28fa43167ad</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>
    </d2p1:_list>
  </checkListAnswers>
  <comments xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list />
  </comments>
  <directSalesAgent xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>6f99f86a-5b1b-4f73-bdc3-388e0b7cf417</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgent>
  <directSalesAgentSuperVisor xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>d57db20d-9b3a-4345-849e-d5a0d0d88f70</d3p1:internalValue>
    </d2p1:_id>
  </directSalesAgentSuperVisor>
  <photos xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfPhotoDataContractEx>
        <d2p1:_dataContract xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" z:Id="i3">
          <d2p1:_isDirty>true</d2p1:_isDirty>
          <d2p1:_id xmlns:d6p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
            <d6p1:internalValue>507f45d1-ce3a-4ec2-a343-d0b83cfb7bc8</d6p1:internalValue>
          </d2p1:_id>
          <d2p1:_key>false</d2p1:_key>
          <d2p1:_keyIdentifier>SurrogateKey</d2p1:_keyIdentifier>
          <Content i:nil="true" />
          <Taken>2013-03-05T17:49:06.294006+02:00</Taken>
        </d2p1:_dataContract>
        <d2p1:_description i:nil="true" />
        <d2p1:_hasDataContract>true</d2p1:_hasDataContract>
        <d2p1:_id xmlns:d5p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
          <d5p1:internalValue>507f45d1-ce3a-4ec2-a343-d0b83cfb7bc8</d5p1:internalValue>
        </d2p1:_id>
      </d2p1:IdentityDataReferenceOfPhotoDataContractEx>
    </d2p1:_list>
  </photos>
  <salesPoint xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts">
    <d2p1:_dataContract xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Project.DataContracts" i:nil="true" />
    <d2p1:_description i:nil="true" />
    <d2p1:_hasDataContract>false</d2p1:_hasDataContract>
    <d2p1:_id xmlns:d3p1="http://schemas.datacontract.org/2004/07/Organization.Domain">
      <d3p1:internalValue>692a294a-2d1b-4026-9693-0c0ce552a2fb</d3p1:internalValue>
    </d2p1:_id>
  </salesPoint>
  <stockCounts xmlns:d2p1="http://schemas.datacontract.org/2004/07/Organization.DataContracts" i:nil="true" />
</VisitDataContractEx>

使用Fiddler调整XML并测试提交,我已将问题缩小到_list元素下的元素名称:

.NET:

    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractExX8I0_S_SPU>

    <d2p1:_list>
      <d2p1:IdentityDataReferenceOfCheckListAnswerDataContractEx>

这是我的数据序列化代码:

public string Serialize<TDataContract>(object obj)
{
    var builder = new StringBuilder();
    var serializer = new DataContractSerializer(typeof(TDataContract));
    var xmlWriter = XmlWriter.Create(builder);
    serializer.WriteObject(xmlWriter, obj);
    xmlWriter.Close();

    return builder.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", string.Empty);
}

这是一个必须由Mono团队解决的错误,还是有人建议可能的解决方法?

修改

我一直在进一步缩小这个问题,它不是关于列表,而是关于每个实现选择XML元素名称的方式。

IdentityDataReference采用泛型类型,在这种情况下,它的类型为CheckListAnswerDataContractEx

IdentityDataReference也恰好位于分布式DLL中(我有源代码),所以我怀疑DataContractSerializer是使用反射来自动计算出名称,也许是因为它是一个单独分布的DLL ,.NET将X8I0_S_SPU追加到最后,但Mono不是。

我还发现我可以向DataContractAttribute添加名称参数,如下所示:[DataContract(Name = "IdentityDataReference")]它将生成的名称覆盖为IdentityDataReference,它甚至不会尝试添加Of Type指定时。

不幸的是,当我指定名称并尝试反序列化数据时,快速测试显示Mono遇到运行时异常。

现在我更好地理解了这个问题,我正在尝试制作一个复制问题的孤立项目。

修改 - 标记为已解决:

我很多年前就从这个项目开始了,但是由于我今天在遇到同样的问题时会感觉到同样的问题,所以我决定关闭它。当时我们希望能够实现“免费”无痛的跨平台集成,而现有的WCF服务没有额外的工作,结果证明是天真的。

今天如果提出相同的要求,我会选择更加跨平台友好的通信协议。如果我无法替换现有的WCF基础架构,那么我会创建某种facade和/或adapter(可能在不同的解决方案中),这些服务通过使用JSON序列化的WebAPI来公开服务,在后台与原始WCF服务交谈。

2 个答案:

答案 0 :(得分:3)

如果您在不同平台之间进行通信(即使.NET和Mono尝试相同),您应该避免使用DataContractSerializer。还有其他可能的问题,而不仅仅是这个bug。例如,如果您更改服务器上的类,则所有客户端可能会停止工作,反之亦然。在服务器 - 客户端方案中,您无法完全控制双方,这可能是一个大问题。

我会将DataContractSerializer更改为XmlSerializer,您可以更好地控制双方。甚至可以在XML中实现自己的序列化,您可以在其中考虑未来的升级。如果在一台服务器上添加一些新属性,则可以以某种方式更新解串器,如果某个旧客户端缺少该新属性,则可以处理。

答案 1 :(得分:0)

或许解决方法是使用svcutil应用程序生成代理,然后使用相同的代理。 http://tutorials.csharp-online.net/WCF_Essentials%E2%80%94Generating_the_Proxy

一般来说,我认为你应该开始使用datacontract的命名空间,因为它帮助我多次识别参考版本问题,这对于代码运行代码的版本来说非常好。但那是另一个差事:)

也许在进行引用时,如果可以添加对包含接口的公共库的引用,则可以使用服务引用设置“从引用的程序集中重用类型”,这将使它们不会使自己的类型达到相同的扩展

最后有一个,在服务引用下显示所有文件可见的Reference.svcmap,这个xml包含一个元素'CollectionMappings',通常需要为我的列表指定行为,本文给出了一些见解:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/09eefbbc-bf63-4aa3-a0cb-01a9dbd7f496/problem-sharing-custom-collection-types-between-service-and-client

这是我的五分钱调试提示,
干杯