【发布时间】:2009-08-18 04:56:32
【问题描述】:
我正在尝试编写一个debugging tool,它允许用户以纯文本形式查看 WCF 的新二进制 XML 格式 (application/soap +msbin1)。一旦我找到XmlDictionaryReader 课程,我以为我会在几分钟内完成,但它没有按预期工作。
private string DecodeBinaryXML(byte[] binaryBuffer)
{
if (binaryBuffer == null)
{
return "";
}
try
{
var doc = new XmlDocument();
using (var binaryReader = XmlDictionaryReader.CreateBinaryReader(binaryBuffer, XmlDictionaryReaderQuotas.Max))
{
doc.Load(binaryReader);
binaryReader.Close();
}
var textBuffer = new StringBuilder();
var settings = new XmlWriterSettings()
{
// lots of code not relevant to the question
};
using (var writer = XmlWriter.Create(textBuffer, settings))
{
doc.Save(writer);
writer.Close();
}
return textBuffer.ToString();
}
catch (Exception ex)
{
// just display errors in the text viewer
return ex.ToString();
}
}
我在网上找到或自己生成的每个“soap+msbin1”示例都会在 doc.Load() 处引发解析异常。
为了看看发生了什么,我创建了一个简单的测试应用程序并从另一个方向解决了问题。
// client
static void Main(string[] args)
{
var binding = new CustomBinding(new TextMessageEncodingBindingElement(),
new HttpTransportBindingElement());
var proxy = ChannelFactory<IService1>.CreateChannel(binding,
new EndpointAddress("http://ipv4.fiddler:25381/Service1.svc"));
Console.WriteLine(proxy.Echo("asdf"));
}
// shared interface
[ServiceContract()]
public interface IService1
{
[OperationContract]
string Echo(string input);
}
// server
public class Service1 : IService1
{
public string Echo(string input)
{
return "WCF says hi to: " + input;
}
}
运行它会启动一个如下所示的 http 请求:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/IService1/Echo</a:Action>
<a:MessageID>urn:uuid:21a33e81-bfab-424f-a2e5-5116101a7319</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">http://ipv4.fiddler:25381/Service1.svc</a:To>
</s:Header>
<s:Body>
<Echo xmlns="http://tempuri.org/">
<input>asdf</input>
</Echo>
</s:Body>
</s:Envelope>
我以两种不同的方式将此 XML 转换为二进制。一、使用XmlDictionaryWriter:
$fs = [system.io.file]::Create("c:\temp\soap.bin")
$writer = [system.xml.xmldictionarywriter]::CreateBinaryWriter($fs)
$xml = [xml] (gc C:\temp\soap.xml)
$xml.Save($writer)
$writer.Close(); $fs.Close()
然后,使用 WCF 和相同的网络嗅探器:
@@ -1,7 +1,7 @@
// client
static void Main(string[] args)
{
- var binding = new CustomBinding(new TextMessageEncodingBindingElement(),
+ var binding = new CustomBinding(new BinaryMessageEncodingBindingElement(),
new HttpTransportBindingElement());
方法 #1 给出了 397 字节的二进制外观。方法 #2 显示了 169 字节的非常不同的二进制粘液。除了出现在两个输出中的一些字符串之外,我没有看到这两种编码有很多相似之处。难怪 XmlDictionaryReader 无法理解 WCF 服务的输出!
解码这种格式有什么秘诀,还是我完全走错了路?
【问题讨论】: