ASP.NET Web API and Protocol Buffers

Β· 614 words Β· 3 minutes to read

Protocol Buffers are a super efficient and very flexible way of serializing structured data. Developed at Google, provide the developers lightspeed serialization and deserialization capabilities.

There a handful of .NET implementations, the most popular one, called protobuf-net, created by Marc Gravell from StackExchange. On top of that library, WebApiContrib project has a Web API Protocol Buffers formatter ready for you to plug in.

More after the jump.

Why? πŸ”—

Protocol Buffers can give you a performance boost up to serveral orders of magnitude better than other serializers, such as DataContractSerializer or JSON.NET. Demis Bellot wrote a nice comparison of these, where you can see how Protocol Buffers stacks against other.

Another advantage, in addition to speed, is that it’s incredibly dense (provides a minimal output), making it very suitable for sending over the wire. It is not human readable (binary) and the schema is required to correctly deserialize a message, so that makes it a bit problematic for public use, but as far as I am concerned, most (if not all) internal APIs should use Protocol Buffers for performance reasons.

Installation πŸ”—

The media type formatter for Protocol Buffers has actually been available as part of WebApiContrib (written for the project by Christian Weyer) for a while now. This weekend we have made a few changes to improve it and give you more flexibility.

As you might expect, you can install the formatter from Nuget:

PM> Install-Package WebApiContrib.Formatting.ProtoBuf  

If you wish to have a look at the source, that’s obviously available at WebApiContrib Github pages.

Using Protocol Buffers with Web API πŸ”—

For starters you need to register the formatter against your Web API configuration, at application startup:

config.Formatters.Add(new ProtoBufFormatter());  

The registered media type by default is application/x-protobuf. The types that you wan to return serialized to protobuf format need to be decorated either with protobuf=net specific attributes (note order is necessary to specify):

[ProtoContract]  
public class Item  
{  
[ProtoMember(1)]  
public int Id { get; set; }  
[ProtoMember(2)]  
public string Name { get; set; }  
[ProtoMember(3)]  
public long Value { get; set; }  
}  

Or with regular DataContract attributes.

[DataContract]  
public class Item  
{  
[DataMember(Order = 1)]  
public int Id { get; set; }  
[DataMember(Order = 2)]  
public string Name { get; set; }  
[DataMember(Order = 3)]  
public long Value { get; set; }  
}  

The latter approach is recommended since the behavior defined by them can be picked up by other Web API formatters such as JSON and XML. In this case, just like before you must specify the order to get a reliable key number and guarantee the data integrity!

This is enough to get you started - so you can now request your API with this accept headers and that would produce protobuf output.

By default, protobuf-net uses UseImplicitZeroDefaults set to true - this means it will omit properties with default values (not set explicitly). Since this can omit things like bool and int, for this particular Web API implementation, we reset it to false arbitrarily so that you don’t run into unexpected issues, such as missing properties.

However, this is not everything. It is known the first (few) serializations with protobuf-net can be slow. If you are seeking really extreme performance, you can precompile specific types. ProtoBufFormatter exposes a static property Model (of protobuf-net RuntimeTypeModel type) which is intended to be a hook for you.

For example:

ProtoBufFormatter.Model.Add(typeof (Item), true);  
ProtoBufFormatter.Model.CompileInPlace();  

This is not necessary but will give you performance improvement during first requests.

All in all - it’s a big performance boost, and the formatter is ready to be plugged in - so go ahead and boost your API performance!

PS: If you have any issues, make sure to file a bug!

About


Hi! I'm Filip W., a cloud 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 and on Mastodon.

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