DataContractSerializer和反序列化Web服务响应类型

4

我正在使用调用Web服务并在客户端使用WCF生成的服务参考。 我已将从测试服务接收到的不带SOAP信封和正文标记的XML响应保存到磁盘中。我想从磁盘加载它们并从中创建对象。让我们看看来自我的Web服务的以下方法:

SomeMethodResponse SomeMethod(SomeMethodRequest req)

我手动(通过SOAP UI)将响应保存到磁盘文件中,示例响应:

<SomeMethodResponse xmlns="http://myNamespace">
    <SomeMember1>value</SomeMember1>
</SomeMethodResponse>

然后我尝试使用以下方式从文件中反序列化对象:

DataContractSerializer dcs = 
  new DataContractSerializer(typeof(SomeMethodResponse))

这个失败了——序列化器报错,它期望在命名空间为 'http://schemas.datacontract.org/2004/07' 的元素中找到了在 'http://myNamespace' 中的元素。

问题: 为什么DataContractSerializer 不使用在 SomeMethodResponseType 上声明的命名空间: XmlTypeAttribute(Namespace="http://myNamespace")

我可以通过在DataContractSerializer构造函数中显式提供命名空间和根元素来解决这个问题。但是,然后会出现类似下面的错误信息:

XML文档的最后一行出现错误,在 X 行 Y 列 'EndElement' 命名空间'httpmyNapespace' 中的'SomeMethodResponse 不应该出现。 期望元素'someNameField'。

SomeName 是 web 服务使用的 XSD 中的一个元素。它也是 SomeMethodResponse 类型的属性,由名为 someNameField 的私有字段支持。看起来 DataContractSerializer 正试图反序列化字段以及属性。

如何反序列化我从磁盘保存的 XML 并获得与 SomeMethod 返回相同类型的对象?

谢谢, Matra


...但是为什么我们在SomeMethodResponse类的DataContractAttribute的Namespace属性中定义了命名空间,还要指定命名空间呢?你有没有成功地不使用你所说的解决方法? - Nilzor
2个回答

5

您的XML响应明显具有XML命名空间:

<SomeMethodResponse xmlns="http://myNamespace">
    <SomeMember1>value</SomeMember1>
</SomeMethodResponse xmlns="http://myNamespace">

所以,为了正确地读取和反序列化,您需要告诉您的DataContractSerializer有关此命名空间的信息:
DataContractSerializer dcs = 
    new DataContractSerializer(typeof(SomeMethodResponse),
                               "SomeMethodResponse", "http://myNamespace")

通过在构造函数中指定此默认的XML命名空间,现在应该能够读取和反序列化此XML了。
另一个错误信息是:
“在XML文档的最后一行,第X行第Y个位置出现错误。'EndElement' 来自命名空间'httpmyNapespace’ 的'SomeMethodResponse'未被期望。 期望元素'someNameField'。”
这是由于您的结束元素有一个命名空间,这是非常不寻常、以前从未见过的事情。
</SomeMethodResponse xmlns="http://myNamespace">

只需删除多余的命名空间,就可以解决问题!

</SomeMethodResponse>

Marc,感谢您的回答。然而,这不是一个问题。如下所述,我已经尝试过“可以通过显式提供命名空间和根元素来解决DataContractSerializer构造函数的问题”。结束元素命名空间是复制粘贴错误(在发布问题之前,我手动生成了简单的XML)-它在真实的XML中不存在。 - matra
@Matra:好的,那么问题到底是什么呢? - marc_s

5

让我回答自己的问题:第二个错误消息的原因是svcUtil实际上悄悄地选择使用XmlSerializer而不是DataContractSerializer。通过阅读XmlTypeAttribute的帮助文档,我发现了这一点-MSDn说明了控制在由XmlSerializer序列化时生成的XML模式。;-)所以我们回到了老的XmlSerializer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接