MSMQ JSON message formatter

Use JSON to serialize and deserialize message queue messages

Storing objects in the message queue (MSMQ) is based on the serialization of the object instance using some of the serializes, basically any class the implements IMessageFormatter. Most commonly used ones are BinaryMessageFormatter and XmlMessageFormatter.

I prefer XmlMessageFormatter over BinaryMessageFormatter, mostly because messages are stored in a readable format inside the queue, so in case something goes wrong you can direly check the content of the message using built Computer Management MMC (Microsoft management console) in the.

Not so nice thing with storing messages in XML is that it is not so small format for storing. Logically, it is a lot better to use JSON but since there is not out of the box class in .NET framework, people still decide to use XmlMessageFormatter. Luckily, since formatter of the MessageQueue object can be any class which implements IMessageFormatter, it is quite easy to write new message formatter for the MessageQueue class.

using NetJSON;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading.Tasks;
namespace MessageQueuing
{
public class JsonMessageFormatter<T> : IMessageFormatter
{
private Encoding encoding;
public JsonMessageFormatter()
{
this.encoding = Encoding.UTF8;
}
public JsonMessageFormatter(Encoding encoding)
{
this.encoding = encoding;
}
public bool CanRead(Message message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
var stream = message.BodyStream;
return stream != null
&& stream.CanRead
&& stream.Length > 0;
}
public object Clone()
{
return new JsonMessageFormatter<T>(encoding);
}
public object Read(Message message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
using (var reader = new StreamReader(message.BodyStream, encoding))
{
var json = reader.ReadToEnd();
return NetJSON.NetJSON.Deserialize<T>(json);
}
}
public void Write(Message message, object obj)
{
          if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            string json = NetJSON.NetJSON.Serialize(obj);
            message.BodyStream = new MemoryStream(encoding.GetBytes(json));
        }
    }
}
    

The size of the messages

As I mentioned, the main advantage of this format for storing messages in MSMQ is size. To prove this, I used the following sample class as a message and add it to queue using both Json and Xml message formatters.

namespace MessageQueuing.TestApplication
{
    public class SampleModel
    {
        public string ID
        {
            get; set;
        }
        public DateTime TimeCreated
        {
            get; set;
        }
    }
}
    

For storing and reading the messages I used MessageQueueManager library which wraps build in MSMQ .NET classes for easier usage.

            /* Using JSON formatter */
            using (var queueManager = new MessageQueueManager<SampleModel>(@".\private$\TestQueue", new JsonMessageFormatter()))
            {
                queueManager.AddMessage(new SampleModel() { ID = Guid.NewGuid().ToString(), TimeCreated = DateTime.Now });
            }

            /* Using XML formatter */
            using (var queueManager = new MessageQueueManager<SampleModel>(@".\private$\TestQueue", new XmlMessageFormatter()))
            {
                queueManager.AddMessage(new SampleModel() { ID = Guid.NewGuid().ToString(), TimeCreated = DateTime.Now });
            }
    

This sample code will put two messages of the same type to message queue and you can see the obvious difference in size.

Msmq Formatters

However, both of the messages are still readable and you can still check the content of them from the MMC.

The speed

The main focus of JsonMessageFormatter is to reduce the size, but apparently the speed is also improved with the new formatter. Again, to cut the story, the following is a simple test which uses same POCO class from the size test.

            var JsonTimer = Stopwatch.StartNew();
            new JsonMessageFormatter().Write(new Message(), new SampleModel());
            JsonTimer.Stop();

            var XmlTimer = Stopwatch.StartNew();
            new XmlMessageFormatter().Write(new Message(), new SampleModel());
            XmlTimer.Stop();

            Console.WriteLine("JSON: {0}", JsonTimer.ElapsedMilliseconds);
            Console.WriteLine("XML: {0}", XmlTimer.ElapsedMilliseconds);
    

Result is the following:

Performances

As you can see, there is no huge gap in the speed, but still few millisecond during a large traffic volume can make a big difference sometime.

 

 

 

References

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article