Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I found a foible in Microsoft's implementation of Message.ToString(). Then I figured out the cause and found a solution.</p> <p>Message.ToString() <em>may</em> have the Body contents as "... stream ...".</p> <p>This means that the Message was created using an XmlRead or XmlDictionaryReader that was created from a Stream that hasn't been read yet.</p> <p>ToString is documented as NOT changing the State of the Message. So, they don't read the Stream, just put in a marker that there is on.</p> <p>Since my goal was to (1) get the string, (2) alter the string, and (3) create a new Message from the altered string, I needed to do a little extra.</p> <p>Here's what I came up with:</p> <pre><code>/// &lt;summary&gt; /// Get the XML of a Message even if it contains an unread Stream as its Body. /// &lt;para&gt;message.ToString() would contain "... stream ..." as /// the Body contents.&lt;/para&gt; /// &lt;/summary&gt; /// &lt;param name="m"&gt;A reference to the &lt;c&gt;Message&lt;/c&gt;. &lt;/param&gt; /// &lt;returns&gt;A String of the XML after the Message has been fully /// read and parsed.&lt;/returns&gt; /// &lt;remarks&gt;The Message &lt;paramref cref="m"/&gt; is re-created /// in its original state.&lt;/remarks&gt; String MessageString(ref Message m) { // copy the message into a working buffer. MessageBuffer mb = m.CreateBufferedCopy(int.MaxValue); // re-create the original message, because "copy" changes its state. m = mb.CreateMessage(); Stream s = new MemoryStream(); SmlWriter xw = CmlWriter.Create(s); mb.CreateMessage().WriteMessage(xw); xw.Flush(); s.Position = 0; byte[] bXML = new byte[s.Length]; s.Read(bXML, 0, s.Length); // sometimes bXML[] starts with a BOM if (bXML[0] != (byte)'&lt;') { return Encoding.UTF8.GetString(bXML,3,bXML.Length-3); } else { return Encoding.UTF8.GetString(bXML,0,bXML.Length); } } /// &lt;summary&gt; /// Create an XmlReader from the String containing the XML. /// &lt;/summary&gt; /// &lt;param name="xml"&gt;The XML string o fhe entire SOAP Message.&lt;/param&gt; /// &lt;returns&gt; /// An XmlReader to a MemoryStream to the &lt;paramref cref="xml"/&gt; string. /// &lt;/returns&gt; XmlReader XmlReaderFromString(String xml) { var stream = new System.IO.MemoryStream(); // NOTE: don't use using(var writer ...){...} // because the end of the StreamWriter's using closes the Stream itself. // var writer = new System.IO.StreamWriter(stream); writer.Write(xml); writer.Flush(); stream.Position = 0; return XmlReader.Create(stream); } /// &lt;summary&gt; /// Creates a Message object from the XML of the entire SOAP message. /// &lt;/summary&gt; /// &lt;param name="xml"&gt;The XML string of the entire SOAP message.&lt;/param&gt; /// &lt;param name=""&gt;The MessageVersion constant to pass in /// to Message.CreateMessage.&lt;/param&gt; /// &lt;returns&gt; /// A Message that is built from the SOAP &lt;paramref cref="xml"/&gt;. /// &lt;/returns&gt; Message CreateMessageFromString(String xml, MessageVersion ver) { return Message.CreateMessage(XmlReaderFromString(xml), ver); } </code></pre> <p>-Jesse</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload