By default ASP.NET core API methods operate on JSON: they deserialize JSON from request/response body to model type and back. JSON is everywhere and works well… unless you have very high throughput requirements. There are many alternative formats, but Google’s serialization format Protocol Buffers is one of the most used. It has overgone some changes recently: the old proto2 syntax is replaced with proto3. The latter even has an official C# support.
The old proto2 used to have unofficial C# ports, and many ASP.NET MVC samples on the internet are based on those. I couldn’t find a working proto3 version, so I created my own.
To create custom input and output types for ASP.NET two interfaces need to be fullfilled: IInputFormatter and IOutputFormatter. The easiest way to do this is to inherit from InputFormatter and OutputFormatter base classes. Basically ASP.NET MVC tells the content type, content and desired target type, and then custom formatter needs to act on those.
Naturally this all needs to work for all possible types, otherwise the formatters would not be reusable. Proto3 has some strangeness in its APIs, like some of the useful constructors being internal. Luckily with some source code reading one can find the method that does the real work when the actual type is not known on compile time: IMessage.MergeFrom(). Working Input and output formatters are below:
Formatters need to be registered for ASP.NET MVC to use them. This can be done in the ConfigureServices method:
And that’s it, now you can control the desired format with requests by using either application/json or application/x-protobuf as content and accept types. You can even mix and match: send in JSON but request protobuf back.