当它是非法XML时,如何清理服务的响应?

时间:2011-10-11 13:10:44

标签: xml wcf soap .net-4.0

所以我相信我理解这些概念,并且我认为我应该使用IClientMessageInspector,但在我看来,我必须使用System.ServiceModel.Channels.Message主体的所有工具都需要在其中使用XML对象我不能做的.NET因为,这个消息的正文是非法的XML。最终,消息是这样的:

[random number]
<validXml />
[other random number]

例如:

379
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <ns1:getVersionResponse>
   <ns1:getVersionResponse xsi:type="xsd:string">1.2.3</ns1:getVersionResponse>
  </ns1:getVersionResponse>
 </soapenv:Body>
</soapenv:Envelope>
0

这是一个可行的例子,除了以上是无效的XML这一事实(正是我首先要这样做的原因!):

public class CleanRandomNumbersInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        const int tenMegabytes = 10485760;
        var buffer = reply.CreateBufferedCopy(tenMegabytes);
        var copyToRead = buffer.CreateMessage();
        string body;

        using (var reader = copyToRead.GetReaderAtBodyContents())
        {
            body = reader.ReadOuterXml();
        }

        // Now that we have the text, modify it
        body = body.Trim('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0');

        // Shove it back into the message
        var copyToPassOn = buffer.CreateMessage();
        using (var stream = GenerateStreamFromString(body))
        {
            var writer = XmlDictionaryWriter.CreateTextWriter(stream);
            copyToPassOn.WriteBodyContents(writer);
        }

        // Implement this method to inspect/modify messages after a message
        // is received but prior to passing it back to the client 
        Console.WriteLine("AfterReceiveReply called");
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        // GNDN
        return null;
    }

    private static Stream GenerateStreamFromString(string s)
    {
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
}

最终,是的,我知道,这是一项糟糕的服务。但是,在对方修复此问题之前,我需要使用它。我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

您可以使用自定义消息编码器(包装原始编码器,并在MessageEncoder.ReadMessage的实现中删除在将正文传递给原始编码器之前删除任何无关字节)。

但这是非常糟糕的XML吗?这看起来像一个分块传输编码(参见http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html,第3.6.1节) - 检查HTTP头是否找到Transfer-Encoding: chunked标头,然后由HTTP传输来删除这些块。 WCF中的HTTP传输可以处理那些,你在哪里看到这个问题?

答案 1 :(得分:1)

我认为如果没有完全绕过API,你将无法在你的.Net应用程序中完成它。

我的建议是为这个Web服务编写一个小帮助代理服务,它可以加载它,剥离垃圾,并输出有效的XML。

然后您的主应用程序将能够从您的代理服务器读取它作为普通的XML SOAP服务,并且不需要知道他们发送的错误代码。

然后,当他们自己修复服务时,您只需将应用程序中的URL更改回原始服务,然后关闭代理;主应用程序不需要更改代码,但之后也不会留下任何冗余代码。