How can I get the content of a message from System.ServiceModel.Channels.Message?

I have a message contract that I go to my wcf service and I have a message inspector that I use to find what was posted by a wcf client. I have a message, but I don't know how to get data from it. my next post request I go to wcf service.

[MessageContract]
public  class MyMessageRequest
{
    [MessageBodyMember]
    public string Response
    {
        get;
        set;
    }

    [MessageHeader]
    public string ExtraValues
    {
        get;
        set;
    }
}

      

The method in which I receive the message is as follows:

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
        MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);

        request = buffer.CreateMessage();
        Console.WriteLine("Received:\n{0}", buffer.CreateMessage().ToString());
        return null;
}

      

I want to see the Response and ExtraValues ​​values ​​from the post, Please help me on this.

+3


source to share


2 answers


I think what you want

http://msdn.microsoft.com/en-us/library/system.servicemodel.description.typedmessageconverter.frommessage.aspx

where a



(new TypedMessageConverter<MyMessageRequest>()).FromMessage(msg)

      

will provide you with the object you need.

+3


source


I found a weak spot in Microsoft's Message.ToString () implementation. Then I found out the reason and found a solution.

Message.ToString () can have Body content as "... stream ...".

This means that the Message was created using an XmlRead or XmlDictionaryReader that was created from a stream that has not yet been read.

It is documented that ToString does NOT change the state of the message. This way they don't read the stream, they just insert the marker that is included.



Since my goal was to (1) get the string, (2) modify the string, and (3) create a new Message from the modified string, I needed to do a little more.

Here's what I came up with:

/// <summary>
/// Get the XML of a Message even if it contains an unread Stream as its Body.
/// <para>message.ToString() would contain "... stream ..." as
///       the Body contents.</para>
/// </summary>
/// <param name="m">A reference to the <c>Message</c>. </param>
/// <returns>A String of the XML after the Message has been fully
///          read and parsed.</returns>
/// <remarks>The Message <paramref cref="m"/> is re-created
///          in its original state.</remarks>
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();
    XmlWriter xw = XmlWriter.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)'<')
    {
        return Encoding.UTF8.GetString(bXML,3,bXML.Length-3);
    }
    else
    {
        return Encoding.UTF8.GetString(bXML,0,bXML.Length);
    }
}
/// <summary>
/// Create an XmlReader from the String containing the XML.
/// </summary>
/// <param name="xml">The XML string o fhe entire SOAP Message.</param>
/// <returns>
///     An XmlReader to a MemoryStream to the <paramref cref="xml"/> string.
/// </returns>
XmlReader XmlReaderFromString(String xml)
{
    var stream = new System.IO.MemoryStream();
    // NOTE: don't use using(var writer ...){...}
    //  because the end of the StreamWriter using closes the Stream itself.
    //
    var writer = new System.IO.StreamWriter(stream);
    writer.Write(xml);
    writer.Flush();
    stream.Position = 0;
    return XmlReader.Create(stream);
}
/// <summary>
/// Creates a Message object from the XML of the entire SOAP message.
/// </summary>
/// <param name="xml">The XML string of the entire SOAP message.</param>
/// <param name="">The MessageVersion constant to pass in
///                to Message.CreateMessage.</param>
/// <returns>
///     A Message that is built from the SOAP <paramref cref="xml"/>.
/// </returns>
Message CreateMessageFromString(String xml, MessageVersion ver)
{
    return Message.CreateMessage(XmlReaderFromString(xml), ver);
}

      

-Jesse

+5


source







All Articles