Theis article shows how to use Protobuf with an ASP.NET Core MVC application. The API uses the WebApiContrib.Core.Formatter.Protobuf Nuget package to add support for Protobuf. This package uses the protobuf-net Nuget package from Marc Gravell, which makes it really easy to use a really fast serializer, deserializer for your APIs.
Code: https://github.com/damienbod/AspNetCoreWebApiContribProtobufSample
Setting up te ASP.NET Core MVC API
To use Protobuf with ASP.NET Core, the WebApiContrib.Core.Formatter.Protobuf Nuget package can be used in your project. You can add this using the Nuget manager in Visual Studio.
Or you can add it directly in your project file.
<PackageReference Include="WebApiContrib.Core.Formatter.Protobuf" Version="1.0.0" />
Now the formatters can be added in the Startup file.
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddProtobufFormatters(); }
A model now needs to be defined. The protobuf-net attributes are used to define the model class.
using ProtoBuf; namespace Model { [ProtoContract] public class Table { [ProtoMember(1)] public string Name {get;set;} [ProtoMember(2)] public string Description { get; set; } [ProtoMember(3)] public string Dimensions { get; set; } } }
The ASP.NET Core MVC API can then be used with the Table class.
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Model; namespace AspNetCoreWebApiContribProtobufSample.Controllers { [Route("api/[controller]")] public class TablesController : Controller { // GET api/tables [HttpGet] public IActionResult Get() { List<Table> tables = new List<Table> { new Table{Name= "jim", Dimensions="190x80x90", Description="top of the range from Migro"}, new Table{Name= "jim large", Dimensions="220x100x90", Description="top of the range from Migro"} }; return Ok(tables); } // GET api/values/5 [HttpGet("{id}")] public IActionResult Get(int id) { var table = new Table { Name = "jim", Dimensions = "190x80x90", Description = "top of the range from Migro" }; return Ok(table); } // POST api/values [HttpPost] public IActionResult Post([FromBody]Table value) { var got = value; return Created("api/tables", got); } } }
Creating a simple Protobuf HttpClient
A HttpClient using the same Table class with the protobuf-net definitions can be used to access the API and request the data with “application/x-protobuf” header.
static async System.Threading.Tasks.Task<Table[]> CallServerAsync() { var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:31004/api/tables"); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf")); var result = await client.SendAsync(request); var tables = ProtoBuf.Serializer.Deserialize<Table[]>(await result.Content.ReadAsStreamAsync()); return tables; }
The data is returned in the response using Protobuf seriailzation.
If you want to post some data using Protobuf, you can serialize the data to Protobuf and post it to the server using the HttpClient. This example uses “application/x-protobuf”.
static async System.Threading.Tasks.Task<Table> PostStreamDataToServerAsync() { HttpClient client = new HttpClient(); client.DefaultRequestHeaders .Accept .Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf")); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:31004/api/tables"); MemoryStream stream = new MemoryStream(); ProtoBuf.Serializer.Serialize<Table>(stream, new Table { Name = "jim", Dimensions = "190x80x90", Description = "top of the range from Migro" }); request.Content = new ByteArrayContent(stream.ToArray()); // HTTP POST with Protobuf Request Body var responseForPost = client.SendAsync(request).Result; var resultData = ProtoBuf.Serializer.Deserialize<Table>(await responseForPost.Content.ReadAsStreamAsync()); return resultData; }
Links:
https://www.nuget.org/packages/WebApiContrib.Core.Formatter.Protobuf/
https://github.com/mgravell/protobuf-net
