tags:

views:

705

answers:

2

I am using a custom endpoint behavior extension to intercept messages as they are received by my WCF service endpoint, using IDispatchMessageInspector. I retrieve the message content like this:


public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    MessageBuffer messageBuffer = request.CreateBufferedCopy(Int32.MaxValue);
    Message message = messageBuffer.CreateMessage();

    using (MemoryStream stream = new MemoryStream())
    {
        using (XmlWriter writer = XmlWriter.Create(stream))
        {
            message.WriteMessage(writer);
            writer.Flush();
            stream.Position = 0;
        }
    }
}

I need to obtain the XML message exactly as it is sent by the client, but the XML that is written to the stream seems to be modified by WCF (or the XmlWriter?). My main problem is that it has modified closing tags: <id /> becomes <id></id> everywhere in the XML message. Is there a way to write the message content as it was received by the endpoint without it being modified (or at least without changing the way the tags are closed?

+1  A: 

I have not tested this, but it might be worth a try.

Idea is that the modification to the xml is being done by the xmlwriter.

You could then get the contents of the message by doing a message.ToString().

EDIT Looks like WCF will change the XML on the server or client side if you send it over as xml.

What you could do is to send the xml over as a byte array, that way WCF will not try to change it.

EDIT 2 The custom message encoder that you mentioned, looks like it both encodes and decodes messages. Would it therefore need to run on the client side as well?

Shiraz Bhaiji
I already tried ToString(), it does not change the closing tags, but it returns a string with garbage binary characters (it does not seem to be encoded right) and anyway this method cannot be used (from MSDN):"The body can be read only once, and ToString does not change the message state. Therefore, the ToString method might not be able to access the body and might substitute a placeholder (for example, “…” or three dots) instead of the message body. Therefore, do not use ToString to log messages if the body content of the messages is important."
mlessard
Unfortunately it is not possible to pass the message as a byte array. I do not control the client applications, the clients can use any application they want to call my service and I must accept any WCF message. For this reason my service accepts a generic WCF message and do not enforce any contract. I really need to modify how WCF handles the message. I think this is possible by writing a custom MessageEncoder but I don't know if it's the best solution: http://msdn.microsoft.com/en-us/library/ms735115.aspx
mlessard
A: 

Ok I solved my problem. It was not Message.WriteMessage that was modifiying the XML closing tags, but MessageBuffer.CreateBufferedCopy! It turns out I no longer need to copy the message before I write it, so not calling CreateBufferedCopy before Message.WriteMessage produces the XML with the closing tags unmodified.

Note however that the written XML might still not be exactly as it was received from the client, WCF stills changes some things like carriage returns, etc. I also experimented with custom WCF MessageEncoders like I mentionned in the comments. It gives you complete control over how WCF creates the Message object from the bytes received on the wire.

So if you need to prevent WCF from modifying things in the data that was received or you need to access the raw bytes of the request, you can use custom MessageEncoders. See this sample from Microsoft:

Custom Message Encoder Sample

Thanks for your help!

mlessard