Using MessagePack with ASP.NET Core MVC

ยท 643 words ยท 4 minutes to read

Some time ago (actually, almost 5 years ago), I blogged about using MessagePack with ASP.NET Web API in order to improve your API’s efficiency over JSON - both in terms of serialization speed and in message payload size.

That code later made it to the WebApiContrib project, where it was released as an add-on to ASP.NET Web API.

I recently had a thought - since we now have WebApiContrib.Core for ASP.NET Core, why not revisit the idea, and create a MessagePack add-on for that too?

MessagePack ๐Ÿ”—

MessagePack is a binary serialization format. Itโ€™s fast and space efficient โ€“ more compact than either JSON or BSON. Moreover, it can serialize pretty much anything that can be represented in a JSON, and, through external ports, it is supported in all mainstream languages (so there are no problems in interacting with an API that is built around a MessagePack media type).

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 (generally speaking) faster to read and write than JSON

You can read more about MessagePack at the official website.

The MessagePack serialization features in this blog post are using the excellent MessagePack for C# library created by Yoshifumi Kawai. You can also find some benchmark comparison in that article.

Using WebApiContrib.Core.Formatter.MessagePack ๐Ÿ”—

Getting started with MessagePack in ASP.NET Core is very simple.

Just download the new WebApiContrib.Core.Formatter.MessagePack Nuget package. It contains a MessagePack input formatter and output formatter, that can be used with ASP.NET Core, along with some extra convenience helpers to wire all the things together.

You then need the following code in your Startup to activate it in your ASP.NET Core application, and off you go!

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore().AddMessagePackFormatters();

    // also works fith Full MVC
    // services.AddMvc().AddMessagePackFormatters();    
}

public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
}

This will set up MessagePack with the default options:

  • the media type used will be application/x-msgpack
  • both input and output formatters will be registered
  • an extension .mp will be mapped to the MessagePack formatter
  • ContractlessStandardResolver will be used for serialization/deserialization - this means that you can use your DTOs without any extra attributes/annotations

Naturally, the MessagePack formatters can co-exist peacefully with other registered formatters, so there is no problem - for example - for your API to support both JSON and MessagePack at the same time.

Additional configuration options ๐Ÿ”—

The formatter settings are quite customizable. For example, if you’d like to register a different content type or file extension, this can be done using a configuration delegate:

services.AddMvcCore().
    AddMessagePackFormatters(c =>
    {
        c.SupportedContentTypes.Add("application/vnd.msgpack");
        c.SupportedExtensions.Add("mpack");
    });

If you would want to customize MessagePack serializer, it’s also possible. You can set up a custom MessagePack resolver as shown below - in this case, the default ContractlessStandardResolver is replaced by StandardResolver, which requires you to annotate the DTOs with serialization attributes:

// sample DTO - needs annotation when using StandardResolver
[MessagePackObject]
public class Book
{
    [Key(0)]
    public string Title { get; set; }

    [Key(1)]
    public string Author { get; set; }
}

services.AddMvcCore().
    AddMessagePackFormatters(c =>
    {
        c.FormatterResolver = StandardResolver.Instance;
    });

You can consult MessagePack for C# documentation for more information on custom resolvers.

By default, the input formatter will buffer the request body. You can disable that behavior via a flag.

services.AddMvcCore().
    AddMessagePackFormatters(c =>
    {
        c.SuppressReadBuffering = true;
    });

If you do not wish to use the extension methods provided by the library, you can also register the formatters manually. This way you can - for example - only enable MessagePack for HTTP responses and not for requests.

services.AddMvcCore(o =>
    {
        o.OutputFormatters.Add(new MessagePackOutputFormatter(new MessagePackFormatterOptions()));
    });

The source is located here in the WebApiContrib.Core repo.

About


Hi! I'm Filip W., a software architect from Zรผrich ๐Ÿ‡จ๐Ÿ‡ญ. I like Toronto Maple Leafs ๐Ÿ‡จ๐Ÿ‡ฆ, Rancid and quantum computing. Oh, and I love the Lowlands ๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP