user192936
user192936

Reputation:

Modifying XML response in WCF; broken XML

I am trying to modify response from a Web Service using a ClientMessageInspector. At some point I need to create a Message from a modified XMLStream. The content of the stream is below:

<soapenv:Envelope xmlns:soapenv="http://env" xmlns:xsd="http://xsd" xmlns:xsi="http://xsi" xmlns:v1="http://v1">
    <soapenv:Body>
        <v1:VM>
            <SH>
                <a>aa</a>
                <b>bb</b>
            </SH>
        </v1:VM>
    </soapenv:Body>
</soapenv:Envelope>

I try to create the message using:

System.Xml.XmlReader XMLReader = System.Xml.XmlReader.Create(XMLStream);
Message ModifiedReply = System.ServiceModel.Channels.Message.CreateMessage(OriginalReply.Version, null, XMLReader);

However when I print the Message content with Message.ToString() I get:

<s:Envelope xmlns:s="http://env">
    <s:Header />
        <s:Body>
            ... stream ...
        </s:Body>
</s:Envelope>

How can I prevent "...stream..." and get the actual XML parts?

Upvotes: 3

Views: 1301

Answers (1)

carlosfigueira
carlosfigueira

Reputation: 87308

A message when created from a XmlReader will always print out ...stream... as its body. Since the reader is a forward-only view on the underlying XML, it cannot be consumed multiple times, so if ToString were to read the data from the reader, the message wouldn't be able to be used by the rest of the WCF pipeline (such as the encoder, which would write it to the wire).

What you can do, if you really want to see the full message, is to buffer the message yourself, then recreate it later. You can use a MessageBuffer for that. And if you really want the full message contents, ToString may or may not give it to you, so you need to write the message out to force it to be printed.

public class StackOverflow_12609525
{
    public static void Test()
    {
        string xml = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/""
            xmlns:xsd=""http://xsd""
            xmlns:xsi=""http://xsi""
            xmlns:v1=""http://v1"">
        <soapenv:Body>
            <v1:VM>
                <SH>
                    <a>aa</a>
                    <b>bb</b>
                </SH>
            </v1:VM>
        </soapenv:Body>
    </soapenv:Envelope>";
        MemoryStream XmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
        XmlReader reader = XmlReader.Create(XmlStream);
        Message originalReply = Message.CreateMessage(reader, int.MaxValue, MessageVersion.Soap11);
        Console.WriteLine(originalReply); // this shows ...stream...
        Console.WriteLine();

        XmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
        reader = XmlReader.Create(XmlStream);

        Message modifiedReply = Message.CreateMessage(reader, int.MaxValue, originalReply.Version);
        MessageBuffer buffer = modifiedReply.CreateBufferedCopy(int.MaxValue); // this consumes the message

        Message toPrint = buffer.CreateMessage();
        MemoryStream ms = new MemoryStream();
        XmlWriterSettings ws = new XmlWriterSettings
        {
            Indent = true,
            IndentChars = "  ",
            OmitXmlDeclaration = true,
            Encoding = new UTF8Encoding(false)
        };
        XmlWriter w = XmlWriter.Create(ms, ws);
        toPrint.WriteMessage(w);
        w.Flush();
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        modifiedReply = buffer.CreateMessage(); // need to recreate the message here
    }
}

Upvotes: 3

Related Questions