【发布时间】:2010-12-26 19:41:18
【问题描述】:
我成功地构建了一个由 WSDL 中的 svcutil.exe 生成的 WCF 客户端。使用生成的客户端代理类,我可以调用外部服务供应商的 Web 服务。我还成功编写了消息检查器,因为我需要将原始 XML 请求和响应作为完整的 SOAP 消息记录到数据库中。
对于紧急情况,我还需要能够“导入”原始 XML 响应。我发现了很多关于使用 XMLSerializer 或基于消息协定反序列化 WCF 消息的提示。
但是如何根据操作契约反序列化原始 XML 响应?对于第一个测试,我使用一个记录的原始响应,将其保存到文件中,然后尝试将其反序列化为客户端代理中生成的响应类型。不知何故,我必须成功地从类ClientOperation 调用DeserializeReply()。但是如何到达那里?
我很乐意接受任何帮助,因为我是 WCF 的新手... TIA, 斯蒂芬
这是我在马克回答后尝试的:
public static RatingResult DeserializeResponseFromFile(string path)
{
var xmlReader = XmlReader.Create(path);
var message = Message.CreateMessage(xmlReader, int.MaxValue, MessageVersion.Soap11);
var readerAtBodyContents = message.GetReaderAtBodyContents();
var dcs = new DataContractSerializer(typeof(RatingResult), "RatingResponse", "http://rating.webservice.xxx.de");
// Error in line 6 position 7. 'EndElement' 'RatingResponse' from namespace
// 'http://rating.webservice.xxx.de' is not expected.
// Expecting element 'commonDataField'.
var wsResult = (RatingResult)dcs.ReadObject(readerAtBodyContents);
return wsResult;
}
这是记录的 XML 响应文件的一部分,我正在尝试反序列化以键入 RatingResponse:
<soapenv:Envelope xmlns:soapenv="..." xmlns:soapenc="..." xmlns:xsd="..." xmlns:xsi="...">
<soapenv:Header soapenv:encodingStyle="..." />
<soapenv:Body soapenv:encodingStyle="...">
<p933:RatingResponse xmlns:p933="http://rating.webservice.xxx.de">
<RatingReturn href="#id0" />
</p933:RatingResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="..." xsi:type="p878:RatingResult" xmlns:p878="http://output.rating.webservice.xxx.de">
<commonData href="#id1" />
<acctData href="#id2" />
<resultData href="#id3" />
</multiRef>
<multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="..." xsi:type="p719:RatingCommonData" xmlns:p719="http://input.rating.webservice.xxx.de">
<requestdate xsi:type="xsd:dateTime">2010-12-24T09:45:09.531Z</requestdate>
...
我猜数据协定序列化程序在反序列化 href 时存在问题。请注意,我尝试“手动”反序列化的消息是使用我注入的消息检查器捕获的。在 Web 服务的“正常”调用中,此消息会被反序列化而不会出现问题。
【问题讨论】:
-
好的,现在我看到了更多你想要做的事情。您在窗口中拥有的是整个 SOAP 消息 - 带有标题和正文等等。您要反序列化的“东西”是
元素 inside 标记。我认为您不能(或不应该)反序列化整个 SOAP 消息 - 尝试获取 SOAP 主体中包含的任何内容,然后反序列化 - 那是您的实际 message payload 将从您的 WCF 方法调用 - 其他一切都只是 SOAP 开销...... -
我已经这样做了。我的测试函数使用
message.GetReaderAtBodyContents()来跳过SOAP 内容。因此,当我调用dcs.ReadObject(readerAtBodyContents)时,阅读器已经指向节点的有效负载。我得到的错误让我怀疑反序列化器无法从 href="#id0" 跳到 id="id0" 的多引用节点。这就是为什么它在第 6 行中出现错误的原因,当它看到它已经到达 的结束标记但期待一些实际编码在这些 href 节点中的字段时。
标签: c# wcf xml-deserialization