For years Windows Communication Foundation (WCF) has been the de-facto framework for building RPCs in the .NET ecosytem. WCF enforced contract based development where the service will expose a contract which the client should adhere to (during compile time itself ) and SOAP messages were used to transport messages between server and client. With .NET Core (a cross platform .net implementation) v3.0 onwards, WCF services were not supported. That means any new service can’t be created using WCF. However, there is still support to consume WCF services from .NET Core 3.x apps.

But ASP.NET Core 3.0 brought in native support for gRPC which is one of the widely popular RPC frameworks built by Google. Support for gRPC from .NET Framework applications were always there, but it wasn’t really natively supported by .NET Framework. More details on this can be found here : https://grpc.io/blog/grpc-on-dotnetcore/

Some of the key concepts of gRPC are:

  1. gRPC by default uses Protocol Buffer as Interface Definition Language(IDL)
  2. gRPC uses HTTP/2 protocol
  3. gRPC supports below different types of RPC
    1. Unary RPC
    2. Server streaming RPC
    3. Client streaming RPC
    4. Bi-directional streaming RPC

In this blog post, I will provide a walk through of getting started with unary gRPC service & client using Visual Studio Code

Prerequisites :

  1. .NET Core 3.x SDK
  2. Visual Studio Code with C# extension on Windows

Step 1 : Create a new grpc service using dotnet CLI

Creating a new dotnet core application is super simple. Just run the below command in commandline

C:\Blog>dotnet new grpc -o firstgRPCService
The template "ASP.NET Core gRPC Service" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on firstgRPCService\firstgRPCService.csproj...
Restore completed in 274.92 ms for C:\Blog\firstgRPCService\firstgRPCService.csproj. Restore succeeded.

Step 2 : Understand the code structure

Let’s explore some of the important changes/additions w.r.t grpc project template that enables grpc in aspnet core.

2.1  firstgRPCService.proj file 

gRPCProjFile

  1. greet.proto is the protobuf file that defines the contract. This is the most important file as this is where all the contract (like models, methods) exposed by this service will be defined
  2. Grpc.AspNetCore is the Nuget package that enables gRPC support for this aspnet core application

2.2  greet.proto file

To work with protocol buffer files in Visual Code, we can use the  vscode-proto3 extension. This extension makes it easy to edit .proto files. You should see similar contents from the file as below:

gRPCProto.png

syntax = "proto3" – indicates the version of protocol buffer used

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

The above snippet defines the service. The service name is Greeter and it exposes a unary rpc method SayHello that takes a parameter of type HelloRequest and responds a type HelloReply. Below are the types definitions for HelloRequest & HelloReply

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

2.3 Startup.cs file

Startup.cs is where the aspnet core service configuration happens. AddGrpc method enables grpc support for this aspnet core service

public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
While first part is just enabling Grpc support, the second part is about configuring the right endpoint for the grpc service, which is done by the following code snippet
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
});
});
GreeterService is the .NET based service implementation of the greet.proto file.

Step 3 : Running the gRPC service

Execute the below command to run the service


C:\Blog\firstgRPCService>dotnet run
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Blog\firstgRPCService
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...

Browsing the URL https://localhost:5001 wil throw the below message in browser : 

Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909

Step 4 : Creating a gRPC Client

gRPC client can be any dotnet or non-dotnet based application which supports http2 protocol. Invoking grpc services directly from browser based web apps is not possible (at the time of this writing) as the browsers don’t natively support http2 yet. There are other frameworks like grpc-web which could help in those cases where grpc services can be invoked from JS directly. For this post, we will be creating a dotnet core client

4.1 Let’s create a new console application using the command


C:\Blog\firstgRPCClient>dotnet new console
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on C:\Blog\firstgRPCClient\firstgRPCClient.csproj...
Restore completed in 126.13 ms for C:\Blog\firstgRPCClient\firstgRPCClient.csproj.

Restore succeeded.

4.2 Add necessary nuget packages for client app

Below are the nuget packages that are required by the console app to talk to grpc service

  1. Grpc.Net.Client – contains .NET Core client
  2. Google.Protobuf – to enable protobuf in the project
  3. Grpc.Tools – used while for tooling, especially while building the application

Run the below commands


C:\Blog\firstgRPCClient>dotnet add firstgRPCClient.csproj package Grpc.Net.Client

C:\Blog\firstgRPCClient>dotnet add firstgRPCClient.csproj package Google.Protobuf

C:\Blog\firstgRPCClient>dotnet add firstgRPCClient.csproj package Grpc.Tools

4.3 Add proto files 

We can copy the protos folder from the service project and paste it to the client project with the same path as protos/greet.proto .

After this we need to include this under the firstgRPCClient.csproj as below
grpcProjFileClient

Note that, in this case we are making the GrpcServices as Client whereas the server project will add it as server This setting will enable the Grpc.Tools to generate server and client specific code appropriately

4.4 Implement the gRPC Client

Building the project would create the GrpcGreeter types from the proto file. Now update the Program.cs file with the below main method implementation


static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client =  new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
    new HelloRequest { Name = "Swaminathan Vetri" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit..."); Console.ReadKey();
}

GrpcChannel is the type that should be used to establish the communication between client and server listening at https://localhost:5001

Once the connection is established, we can create the client and then invoke the RPC methods by passing the required parameters

Step 5 : Testing the grpc service & client

Navigate to the grpc service folder in command prompt and run the command dotnet run That should produce the output as follows :


C:\Blog\firstgRPCService>dotnet run
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Blog\firstgRPCService

Navigate to the grpc client folder in command prompt and run the command dotnet run

If the dotnet dev certs are not trusted yet in the machine, you might receive an error like this.


C:\Blog\firstgRPCClient>dotnet run
Unhandled exception. Grpc.Core.RpcException: Status(StatusCode=Internal, Detail="Error starting gRPC call: The SSL connection could not be established, see inner exception.")
at firstgRPCClient.Program.Main(String[] args) in C:\Blog\firstgRPCClient\Program.cs:line 15
at firstgRPCClient.Program.(String[] args)

To fix the above error, run the below command dotnet dev-certs https --trust


C:\Blog\firstgRPCClient>dotnet dev-certs https --trust
Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not previously trusted. Click yes on the prompt to trust the certificate.
A valid HTTPS certificate is already present.

Now running the client project again, should succeed.


C:\Blog\firstgRPCClient>dotnet run
Greeting: Hello Swaminathan Vetri
Press any key to exit...

Well, we are done creating our first grpc unary service and a client! You can follow the same steps and add further proto files and defined more models & service methods.