Boost up your ASP.NET Web API with MessagePack - StrathWeb

Strath

September 10th, 2012

Boost up your ASP.NET Web API with MessagePack

Because it's like JSON, only more compact!

A while ago I blogged about supporting BSON at your Web API end points. A good alternative to both JSON and BSON has, for quite a while now, been MessagePack.

The main problem with supporting MessagePack in your Web API has been the fact that MessagePack required a strongly typed serializer (in other words, you needed to tell the serializer what type you serialize and deserialize at compile time). There was no easy way to provide support for boxed objects (untyped context) – and Web API media type formatters run against such generic object instances. In face, to be precise, writing to a stream (serializing) has never been a big problem, but reading was very complicated. An easy solution was a type whitelist and a massive if-else block, but such approaches are hardly good ideas.

Four days ago, Yusuke Fujiwara, one of the wizards behind MessagePack for CLI, added support for untyped serializer factory, effectively inviting all of us to start using MessagePack in Web API.

What is MessagePack?

MessagePack is a binary serialization format. It’s very fast, and very space efficient – it’s more compact than both JSON and BSON. Moreover, it can serialize pretty much anything that can be represented in a JSON, and, through external ports, is supported in all mainstream languages.

There are quite a few reasons for these performance/space advantages, mainly due to the way common data types are being stored, for example:
– JSON uses 4 bytes to represent null, MessagePack only requires 1 byte
– JSON uses 2 bytes to represent a typical int, MEssagePack requires 1 byte
and so on.
– Also, since it’s binary, it’s faster to read and write than JSON. There is a great article available here, showing how well MessagePack performs in comparison to JSON and even the “sexy” Protocol Buffers

You can read more about MessagePack at the official website.

Prerequisites

To get started you’d need the MessagePack for CLI library, but not the one from Nuget (that one is old and only supports strongly typed serialization and deserialization) but the latest one. You can either grab it from GitHub and build yourself, or you could download the ZIP-ped DLL directly, from my dropbox.

Creating the formatter

If you follow this blog (or you are semi-familiar with Web API), MediaTypeFormatters should be no mystery to you. They allow us to support various media types and expose data via our Web API endpoint in various formats.

Let’s create the formatter:

I left the two core methods empty on purpose for now. For now we have the supported media type headers – application/x-msgpack and the serialization rules – we only support public, non-abstract, non-interface types – except IEnumerable.

Write to stream

In this case I’m actually using a strongly typed serializer, against object (or rather, against dynamic, but that’s effectively object as well). As I wrote in the beginning, that feature has always worked without problems, it’s the read from stream that was problematic. Not much exciting happens here besides that; we call the void Pack on the serializer, which takes care of writing to our output stream.

Note, because MessagePack is having troubles with interface-based collections, we flush them to list if we deal with such.

Read from stream

In the read portion, we use the new untyped MessagePackSerializer, and in conjuction with an Unpacker object, we read the stream into the generic object.

That stream becomes an object but will be unboxed by Web API into our CLR type.

Using it

Now a quick example on how you’d use if from your .NET client. For the record, this is the simple model I used:

Note, in this case, since we are consuimg it from the client, we can easily use the typed serializer – in this case against my test Url model (I always use “var”, but on the last line I purposefully used the Type indicator, to show at which point our CLR object emerges).

In a similar manner, we’d retrieve a collection:

Finally, if we want to send some data to the Web API in MessagePAck format:

In this case, we use our MediaTypeFormatter to help us with serialization to send over the wire.

As you can see, even with a small amounts of data – retrieving a collection of 5 objects:


1st MessagePack, 2nd JSON, 3rd XML

and retreving a single object and again 5 objects:

MessagePack outperforms JSON in terms of size by about 15%. The gain would be even bigger if we used arrays and different types of ints in the model, as that’s the stuff MessagePack excells at.

Summary and source

MessagePack is a really viable alternative to JSON. Moreover, with the way Web API works, it’s really not a big effort to throw in support for MessagePack in your API as an extra. I have used MessagePack to communicate between .NET clients and it has always worked great.

There are implementations of MessagePack serializers for all major languages, including JavaScript, so theoretically you could use that even in the browser (although, to be honest I have never tried that).

Anyway, I hope you’d find this post useful!

source (gist)

Be Sociable, Share!