如何使用OperationContract反序列化WCF消息
我成功地构建了由 svcutil.exe 从 WSDL 生成的 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 服务的“正常”调用中,该消息可以毫无问题地反序列化。
I succeeded in building a WCF client generated by svcutil.exe from the WSDL. Using the generated client proxy class I can call the web service of an external service supplier. I also succeeded in coding a message inspector, as I need to log both raw XML request and response as full SOAP message to the database.
For an emergency scenario I also need to be able to "import" a raw XML response. I found many hints on using XMLSerializer
or deserializing WCF messages based on the message contract.
But how can I deserialize a raw XML response based on an operation contract? For a first test I use one of the logged raw responses, save it to a file and now try to deserialize it to the response type as generated in the client proxy. Somehow I must succeed in calling DeserializeReply()
from class ClientOperation
. But how to get there?
I happily accept any help as I'm quite new to WCF...
TIA,
Stefan
This is what I tried after Marc's answer:
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;
}
This is part of the logged XML response file, that I'm trying to deserialize to type 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>
...
I guess that the data contract serializer has problems deserializing the href's. Please note that the message I try to deserialize "by hand" was captured using my injected message inspector. In a "normal" call of the web service this message get deserialized without problems.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不太明白你想问什么、想做什么......基于运营合同? 操作契约只是您在操作/方法调用上放置的一个属性,用于将其标记为服务方法......操作契约不执行任何远程涉及序列化或反序列化的操作。 ...您的意思是如何使用 WCF 默认序列化程序 DataContractSerializer 反序列化 XML 消息?
假设您确实想了解HOWTO:使用 DataContractSerializer 反序列化 WCF 消息,那么请尝试以下操作:如果您有来自使用默认 WCF
DataContractSerializer
的服务调用的响应 XML,您应该能够像这样反序列化它(假设您的 XML 序列化响应位于xmlResponse
变量中):I don't really understand what you're trying to ask and to do.... based on an operation contract ?? The operation contract is just an attribute you put on an operation / method call to mark it as a service method .... the operation contract doesn't do anything even remotely involved with serialization or deserialization..... do you mean how to deserialize an XML message using the
DataContractSerializer
which is the WCF default serializer??Assuming you do really mean HOWTO: deserialize a WCF message using the DataContractSerializer, then try this: if you have the response XML from a service call that used the default WCF
DataContractSerializer
, you should be able to deserialize it like this (assuming you have your XML serialized response in axmlResponse
variable):对于将来这样做的任何人。我必须手动从 MSMSQ 中读取 WCF 消息,并从 MSMQ/WCF 消息信封中获取请求对象。操作方法如下:
根代码:
我的合同:
我的数据合同:
我的消息反序列化代码:
For anyone in the future doing this. I had to manually read a WCF message out of the MSMSQ, and get the request object out of the MSMQ/WCF message envelope. Here's how:
Root code:
My contract:
My Data Contract:
My message deserialization code: