Exactly what can be sent in a message? Literally anything …Well not exactly anything but any object can be sent as the body of a message. This is made possible by a mechanism known as Serialization.

Serialization is the process of taking objects and converting their state information into a form that can be stored or transported. The basic idea of serialization is that an object writes its current state, usually indicated by the value of its member variables, to persistent storage. Later, the object can be re-created by reading, or deserializing, the object's state from the storage. Serialization handles all the details of object pointers and circular object references that are used when you serialize an object.

In MSMQ, this process refers specifically to converting an object or set of data into a message that can be sent to a queue and then converting messages retrieved from the queue back into objects or data that the receiving application can process. The component that controls this process is the Formatter. The Formatter property of a MessageQueue contains an instance of a Formatter object which transforms messages when your application reads or writes to the queue. In other words when the application sends messages to the queue, the formatter serializes the object into a stream and inserts it into the message body. When reading from a queue, the formatter deserializes the message data into the Body property of a Message.

On the full .NET Framework there are 3 Formatters provided namely, the ActiveXMessageFormatter, BinaryMessageFormatter and XmlMessageFormatter.

However on NETCF the only Formatter provided is the XmlMessageFormatter (Which uses our new publicly exposed XmlSerializer J - this is my pet feature). You can however write your own custom Formatter that implements the IMessageFormatter. In your custom Formatter for instance, you could encrypt and decrypt your message body and you could also do compression. This would be relatively easy to do as the IMessageFormatter has only 3 public methods. This article details how this can be done in C#.  

The XmlMessageFormatter is the default formatter that an instance of MessageQueue uses to serialize messages written to the queue. Note however that a queue’s default XmlMessageFormatter can be used to write to the queue but it cannot be used to read from the queue until the TargetTypes of TargetTypeNames property on the Formatter is set. This is because the TargetTypes (or TargetTypeNames) property tells the Formatter what schemas to attempt to match when deserializing a message thence allowing the Formatter to interpret the message body. It is recommended that you set the TargetTypes property (instead of the TargetTypeNames property) as type existence will be checked at compile time rather than run time thence reducing the possibility for error.

The following code snippets demonstrates how to use the XmlMessageFormatter to receive an instance of a user defined type (i.e. BookOrder) sent as the body of a message. In this code I assume an instance of a BookOrder has been sent to the private queue and we attempt to retrieve it asynchronously.

  

string qName = @".\private$\mqdemoAck";

 

                  if(!MessageQueue.Exists(qName))

{

                        ackQueue = MessageQueue.Create(qName);

                  }

                  else

                  {

                        ackQueue = new MessageQueue(qName);

                  }

 

                  System.Type[] types = new Type[1];

                  types[0] = typeof(BookOrder);

 

ackQueue.Formatter = new XmlMessageFormatter(types);

      ackQueue.ReceiveCompleted += new

ReceiveCompletedEventHandler(MyReceiveCompleted);

                  ackQueue.BeginReceive();       

                 }

private void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs

asyncResult)

            {

                  try

                  {

                        System.Messaging.Message message =

this.ackQueue.EndReceive(asyncResult.AsyncResult);   

                        if(message.Body is BookOrder)

                        {

                              BookOrder bookOrder = message.Body as BookOrder;

                              //Process bookOrder

                  }

                        else

                        {

                              MessageBox.Show("Message in Queue is not a book

Order");

                        }

                  }

                  catch(MessageQueueException e)

                  {

                        //handle Exception

                  }

                  this.ackQueue.BeginReceive();

            }

    

 

Please see the following documentation for more information on message serialization.

Message Serialization (MSDN)

Formatter Property (MSDN)