A code-first/contract-first approach with gRPC is available with protobuf-net in .NET 6. When starting a gRPC template in Visual Studio 2022, proto files are provisioned by default, but if you have already C# models/contracts defined, you can make use of protobuf-net.
Protobuf
protobuf-net is an implementation on top of protobuf, a protocol buffer that provides a language-neutral, platform-neutral, extensible mechanism for serializing structured data that generates native language bindings.
For more details on gRPC and Protobuf, check the article gRPC in .NET 6
protobuf-net.Grpc
protobuf-net.Grpc is a NuGet package that combines protobuf-net with Grpc.Net, providing:
support for the managed Kestrel (server) and HttpClient (client) HTTP/2 bindings on .NET Core 3.1 and above
code-first or contract-first approach
with code-first support, use any .NET language (C#, VB, F#)
it works with the standard (unmanaged) Grpc.Core implementation if you are limited to .NET Framework (.NET Framework 4.6.1 or .NET Standard 2.0).
On the article gRPC in .NET 6 I used the proto files user.proto, address.proto. In this example, I have converted them into C# models/contracts and services for comparison purposes.
DataMember: Used to serialize the property. Used by specifying message attribute Order.
These are called data contracts, a formal agreement between a service and a client that abstractly describes the data to be exchanged, widely used by Windows Communication Foundation (WCF).
ProtoMember: Used to serialize the property. Used by specifying message attribute Order (implicitly).
Services
The services can be created using ServiceContract and OperationContract attributes, or the new Service and Operation attributes part of protobuf-net.Grpc.
usingSystem.Net;usingGrpcService.Services;usingMicrosoft.AspNetCore.Server.Kestrel.Core;usingProtoBuf.Grpc.Server;varbuilder=WebApplication.CreateBuilder(args);// Add services to the container.
builder.WebHost.ConfigureKestrel(options=>{options.Listen(IPAddress.Any,5000,listenOptions=>{listenOptions.Protocols=HttpProtocols.Http2;});});builder.Services.AddCodeFirstGrpc(config=>{config.ResponseCompressionLevel=System.IO.Compression.CompressionLevel.Optimal;});varapp=builder.Build();// Configure the HTTP request pipeline.
app.MapGrpcService<UserService>();app.MapGrpcService<GreeterService>();app.Run();
Note that HttpProtocols.Http2 must be specified with Kestrel and AddCodeFirstGrpc needs to be attached to the ServiceCollection.
Client:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
usingSystem.Text.Json;usingGrpc.Net.Client;usingGrpcDomain.Interfaces;usingGrpcDomain.Requests;usingProtoBuf.Grpc.Client;varchannel=GrpcChannel.ForAddress("http://localhost:5000");varclient1=channel.CreateGrpcService<IGreeterService>();vargreeting=awaitclient1.GetGreetingAsync(newHelloRequest(){Name="Bill"});Console.WriteLine(greeting.Message);varclient2=channel.CreateGrpcService<IUserService>();varuserDetails=awaitclient2.GetUserAsync(newUserRequest(){Id=1});Console.WriteLine(JsonSerializer.Serialize(userDetails));Console.WriteLine("Press any key to exit...");Console.ReadKey();
From here run the server and launch the client. Bob is your uncle. :)
Join the conversation! Share your thoughts and connect with other readers.