Message: The Most Important WCF Class

Even fairly experienced WCF programmers may never have had to deal with this little gem, however, it is the single most important class in the WCF framework. Why is that? Because the message class provides the fundamental abstraction which represents all data sent or received from any WCF endpoint.

Key Parts

There are four key parts to the message class:

  • Version - The version property contains information about the SOAP and Addressing versions used by the message. WCF fully supports use of non-SOAP messages for which this property is will be None to indicate the lack of any special formatting.
  • Properties - Message properties contain processing information about the message which will not be written to the underlying transport stream as part of the message content. One example of what message properties can be used for is controlling things like HTTP verbs and status codes.
  • Headers - A collection of message headers. A few common headers such as To and Action can be accessed via shortcut properties in the headers collection.
  • Body - You can’t actually access the message body because the Message class abstraction is mean to be used as if the content of the Message was a stream.

It’s Abstract

This will come as a surprise to many people, because the WCF framework does a very good job of hiding this fact, but the Message class itself is an abstract class. So put away any preconceived notions you might have had about how WCF at it’s core can only be used for web services and XML based communication. The fact is that you could create a message class backed directly by a raw binary array if you didn’t want any kind of performance hit for loading the data… as a matter of fact you probably wouldn’t want to even waste your time doing that, because WCF does exactly that when you are using many of the default settings! Actually… it does it even more efficiently than you would probably do it on your own by taking advantage of buffer managers to reduce the number of allocations that need to be made as messages are being created and disposed. So, despite the fact that the underlying abstraction is streaming, WCF actually buffers messages into a byte array by default to allow for higher performance.

It’s Streaming

Once you read the message, it cannot be read again. For this reason, all custom message classes must also provide a MessageBuffer implementation. I won’t talk much about the MessageBuffer class at this point, other than to say that it is also abstract and it is responsible for creating additional “copies” of the message. I say “copies” because the default implementations that are most commonly used by the standard bindings won’t actually “copy” anything. They just return another instance backed by the same internal byte array. This makes for ultra efficient message copying, but is only possible because of another trait of the message… The reason Message implementers must provide their own MessageBuffer implementations is so that the copy operation itself can be as optimized as possible.

It’s Immutable

Well… sort of. The properties and headers of the message can be modified at will, making things like routing logic and header processing much easier to deal with, but the message body itself cannot be modified using the Message or MessageBuffer classes. For this reason, many hooks  in the WCF internals where a Message might need to by modified will pass the message as a ref parameter so it can be swapped for another message.

It’s Not XML

The last basic thing you need to know about the Message class which I already touched on, but should make clear again… the Message class does have to not represent XML data! This may seem like a strange statement if you’ve looked casually at the methods provided by the message class. However, this is only due to the unfortunate naming that the WCF team chose for XmlDictionaryReader and XmlDictionaryWriter, which have a lot of methods for reading and writing XML data, but fully support reading and writing raw binary content as well.

Tags: , ,

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

6 Responses to “Message: The Most Important WCF Class”

  1. Yaron Naveh 22 January 2010 at 11:51 am #

    I was actually doing a similar investigation some time ago to check how much abstract is it really. I was in a need to move totally binary messages in the channel stack. I didn't find any flaws then, but was a little afraid that the Message class is "biased" towards Soap. For example the division to "headers" and "body", the addressing headers that magically fit the WS-Addressing standard etc.

    Based on your experience, if I want to take the Wcf channel stack framework, and use it with my own channels passing my own non-xml messages – am I expected to any specific pitfalls?

    • jezell 22 January 2010 at 4:36 pm #

      No, there are no special pitfalls when dealing with non-SOAP messages. As long as you set the message version to none, you will be fine. If doing REST work, you can use the WebMessageEncoder. Additionally, .NET 4.0 adds ByteStreamMessageEncodingBindingElement.

      http://msdn.microsoft.com/en-us/library/system.se...

  2. Confused by debugger 22 January 2010 at 10:22 pm #

    So if I create a message with a byte array as an argument with a version of none and I look in the debugger it looks like this <base64Binary xmlns="http://schemas.microsoft.com/2003/10/Serialization/">BwAAAAAAAA==</base64Binary>

    Is that XML? How do I get rid of those tags that are messing up my nice compact byte array? Is this just a visual trick of the debugger?

    • jezell 22 January 2010 at 10:28 pm #

      The component responsible for turning the representation of the message into data is the MessageEncoder. You see the base 64 tag because you are using the text message encoder. If you want to send raw binary data, you can implement a custom message encoder class with a custom xml dictionary writer that only writes out the raw byte array and writes it out directly as bytes. This is how the byte stream message encoding in 4.0 works. Message encoders are a pretty easy thing to implement compared to something like channels.

  3. Confused by debugger 22 January 2010 at 10:56 pm #

    Thank you for responding so quickly!

    If I was using a socket I could just write bytes. Why do I have to use the none argument, the action argument and the byte[] argument? Is there a method that just takes a byte array?

    If I have to write a MessageEncoder why do you say WCF supports arbitrary bytes? Isn't that like saying sockets support WCF?

    Are you saying in 4.0 I do not have to write a MessageEncoder?

  4. jezell 24 January 2010 at 1:16 am #

    WCF certainly doesn't go out of it's way to make messaging with anything other than interfaces and objects marked up with attributes easy, but it is possible. This topic is probably worth an entire blog post, so I'll write something up when a get a chance.


Leave a Reply