gRPC in ASP.NET Core

gRPC is a modern, high-performant, language-agnostic, open-source RPC framework which is using HTTP/2. If you are building Microservices; and you need a way to reduce network usage, real-time services to handle streaming requests or responses then you should try gRPC. I bet you are already aware that you can use gRPC in ASP.NET Core

A few days ago, I decided to play with gRPC. FYI, I am using .net core in my day to day job. I would like to learn how gRPC can be used with ASP.Net Core Web APIs to call other Microservices. And here is what I did to start with gRPC for Asp.Net Core.

About gRPC

First of all gRPC stands for Google Remote Procedure Call. gRPC is based on Stubby, a very successful tool for google. gRPC is isolated by design from the transport protocol. The available default protocol is called Protocol Buffers. Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data. If you want to know more about this please check here

gRPC for .Net

The Grpc.Net.Client package supports on .Net Core 3, .NET 5 or later. ASP.NET Core gRPC services can be hosted on all operating system that .NET Core supports. Using  Grpc.Net.Client on .NET Framework or with gRPC-Web requires additional configuration. For more information, see here.

In this post, we’ll just add a gRPC server with an ASP.NET Core project and a rest API client to call those remote procedures, which is also an ASP.NET core project; and I am using C#. .NET types for services, clients, and messages are automatically generated by including *.proto files in a .NET app

gRPC server in ASP.NET Core app

Firstly, we will add a gRPC server within ASP.NET Core

  • Starting with an ASP.NET Core Empty project and calling it JK.gRPC.Server ; Target framework .Net 5.
  • Adding the Grpc.AspNetCore package which is referring to the following three pacakges
    • Grpc.AspNetCore.Server.ClientFactory HttpClientFactory integration the for gRPC .NET client when running in ASP.NET Core
    • Google.Protobuf C# runtime library for Protocol Buffers – Google’s data interchange format.
    • Grpc.Tools to compile .proto files
  • Adding service to Startup -> ConfigureServices method `Se
  • Mapping gRPC endpoint on Startup -> Configure method
app.UseEndpoints(endpoints =>
{
    endpoints.MapGrpcService<GreeterService>();
    endpoints.MapGet("/", async context =>
    {
        await context.Response.WriteAsync("Hello World!");
    });
});
  • Let’s create the GreeterService class. Before implementing the class we need the contract. Here comes the *.proto file where I’ll use proto3
  • Add a folder name Protos and add a file named greet.proto inside the folder, which is basically a Protocol Buffer File
  • Let’s add the following code to the file
// There are 2 version of Protocol Buffers, proto2  and proto3. 
// proto3 is the latest
syntax = "proto3"; 

// The namespcae in C#. Its a hint for the compiler 
// which C# namesapce we should use to refer this file
option csharp_namespace = "JK.gRPC.Server";

// The greeting service definition.
service Greeter {
	// Method: Call this to Send a greeting
	rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
	string name = 1;
}
// The response message containing the greetings.
message HelloReply {
//We are not assigning any value here. 
//1 is the ordinal number 
	string message = 1;
}
  • Next, we need to change the Build Action for the file. Importantly, we will choose Protobuf compiler and Server only for gRPC Stub Classes. This is our gRPC server.
Property window
Properties for the greet.proto file
  • Once you build the project successfully. It will add following ItemGroup in the .csproj file
  <ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
  </ItemGroup>
  • Furthermore, we need to go back to the GreetService class and use Greeter.GreeterBase as the base class
  • If you just type override you will see the method from the proto file
type override
Intellisense for the contract
  • Next, lets implement the SayHello procedure
public override Task<HelloReply> SayHello(HelloRequest request, 
                                          ServerCallContext context)
{
    return Task.FromResult(new HelloReply
    {
        Message = "Hello " + request.Name
    });
}

And now we are done with the simplest gRPC server with ASP.NET Core for now

gRPC client in ASP.NET Core app

In this section, I’ll add a gRPC client within REST API. If you’ve already looked for sample code for a gRPC client for .Net, you may notice that most of the examples are using the Console app as a gRPC client. However, I will use a REST API endpoint to call the gRPC server using HttpClientFactory

  • Starting with an ASP.NET Core Web API project and calling it JK.gRPC.Client ; Target framework .Net 5. I’ve also selected Configure for HTTPS .
  • Right-click on Connected Services and select Add Connected Services A popup window will appear
Connected Services
Connected Services window
  • Select the greet.proto file and Client option as Select they type of class generated
Add new gRPC service reference to generate client code
Add new gRPC service reference to generate client code
  • It will generate the necessery code under the hood. Therefore, It may take some time and the show the added service
After connecting gRPC service
Added service
  • When you add the service as a client it will also include Grpc.AspNetCore nuget package
  • Go to Startup class and register gRPC client within ConfigureServices
services.AddGrpcClient<Greeter.GreeterClient>(opt =>
{
    opt.Address = new Uri("https://localhost:5001");
});
  • Let’s add a GreetController with a Get endpoint
  • We need to inject the Greeter.GreeterClient within the constructor and set it to a class variable _client
  • Add the Get endpoint. We will call the Grpc client and return the response message. After that the controller will look like below
[ApiController]
[Route("[controller]")]
public class GreetController : ControllerBase {
    private readonly Greeter.GreeterClient _client;
    public GreetController(Greeter.GreeterClient client) {
        _client = client;
    }

    [HttpGet("{name}")]
    public IActionResult Get([FromRoute]string name, 
                             CancellationToken cancel) {
        var request = new HelloRequest { Name = name };
        var call = _client.SayHello(request, cancellationToken: cancel);
        return Ok(call.Message);
    }
}

Voila!! That’s our gRPC client calling the server. Let’s run both server and client, and both will open the console windows

ASP.NET API running on kestrel
Both server and client API are running

Now, we need to call the greet URL from the browser or your preferred REST API calling tools e.g. postman or curl. When I put this URL https://localhost:5003/greet/MJK in my browser, it shows me the message

Hello MJK
Showing the resonse from gRPC Server using the gRPC client

Remarks

I tried to keep it as short as possible while talking about gRPC for ASP.NET Core. Please check the documentation to find more. Thus, I hope you enjoyed it reading or following as much I enjoyed writing this. I have added some helpful links below to learn more. Meanwhile, I just want to add few important topics I think you should know

  • For gRPC
    • HTTP/2 is used as the transfer protocol
    • Protocol Buffers is used for serialization
  • For client ASP.Net core API,
    • gRPC clients can automatically be injected into MVC controllers, SignalR hubs and gRPC services
    • Standard HttpClientFactory methods can be used to add outgoing request middleware or to configure the underlying HttpClientHandler of the HttpClient
  • gRPC-Web is needed for the server to use the call the gRPC client from the browser using JavaScript. In addition, A middleware needs to be added, and also we need to cater for CORS.
  • protoc tool is required to generate the client code for the JavaScript client
  • Protocol buffers are much smaller than JSON or XML
  • If you need to remove/change any property, It is better not to use the used Ordinal add a new number.
  • You could use Authorization using JWT or Certificate
  • Most Importantly, please do not forget to share or comment if you like this post

Download the sample

However, if you need to run a local copy then you can download the example code from my GitHub repository. The following command clones the entire repository

git clone https://github.com/jobairkhan/gRPC.git

Helpful Liks

You can find more about gRPC and gRPC on dotnet in these links

I would like to hear your thoughts