Building a gRPC service with C#

1. Overview

gRPC is a language-neutral, platform-neutral remote procedure call (RPC) framework and toolset developed at Google. It lets you define a service using Protocol Buffers, a particularly powerful binary serialization toolset and language. It then lets you generate idiomatic client and server stubs from your service definition in a variety of languages.

In this codelab, you learn how to build a C# service that exposes an API using the gRPC framework. You interact with this service using a console client written in C# that uses the same service description as the service.

What you'll learn

  • The Protocol Buffer language.
  • How to implement a gRPC service using C#.
  • How to implement a gRPC client using C#.
  • How to update a gRPC service.

What you'll need

How will you use this tutorial?

Read it through only Read it and complete the exercises

How would rate your experience with Google Cloud Platform?

Novice Intermediate Proficient

2. Download and build gRPC C# samples

Download samples

Download the gRPC C# sample repository as a zip file and extract it.

Alternatively, you can clone its git repository.

git clone https://github.com/meteatamel/grpc-samples-dotnet.git

Either way, you should have a grpc-samples-dotnet folder with the following contents:

d056832ff4ce0c8f.png

Build the solution

The sample application folder contains GrpcSamples.sln, a Visual Studio solution. Double click to open the solution in Visual Studio. You should see a solution with a number of projects.

61da9ddc86c08019.png

We will go through the projects in more detail in the next section, but first, let's just build the project. Go to Build > Build Solution or Ctrl + Shift + B to build the solution. This will download all the dependencies from NuGet and then compile the application.

In the end, you should see a Build succeeded message in Visual Studio console output.

3. Explore the Greeter sample

Greeter is a simple gRPC sample where a client sends a request with a name and the server responds with a message followed by the name. There is a Greeter project that includes the common service definition (proto file) on which the client and server are based.

Greeter Project

This is the common project shared between the client and the server. It has a greeter.proto which is the gRPC service definition that client and server use. The service definition defines a gRPC service called GreetingService and it has a greeting method that takes in HelloRequest as input and HelloResponse as output.

service GreetingService {
    rpc greeting(HelloRequest) returns (HelloResponse);
}

This is a unary (i.e. no streaming) method where the client sends a single request and gets a single response from the server. You can explore the rest of the contents of greeter.proto. This project also has a script called generate_protos.bat that can be used to generate client and server stubs from the proto file. The project already contains generated client and server stubs, so you don't have to generate them on your own. However, if you change something about the service definition file, you will need to run this script to regenerate the stubs.

Greeter Server

This is the project for gRPC server. Program.cs is the main entrypoint where the port and server implementation is set up. The important class is GreeterServiceImpl.cs. It has a greeting method where the actual functionality is implemented.

public override Task<HelloResponse> greeting(HelloRequest request,
       ServerCallContext context)
{
    return Task.FromResult(new HelloResponse { 
          Greeting = "Hello " + request.Name });
}

Greeter Client

This is the client side of the gRPC service. It also has Program.cs as the entrypoint. It creates a channel to talk to the server and then creates a client with the channel from the generated stub. It then creates a request and sends it to the server using the client stub.

4. Run the Greeter sample

First, start the Greeter Server. Open a command prompt, and navigate to the bin > Debug folder of Greeter Server and run the executable. You should see the server listening.

> C:\grpc-samples-dotnet\GreeterServer\bin\Debug>GreeterServer.exe
GreeterServer listening on port 50051
Press any key to stop the server...

Next, run the Greeter Client. In a separate command prompt, and navigate to the bin > Debug folder of Greeter Server and run the executable. You should see the client sending the request and receiving a response from the server.

> C:\grpc-samples-dotnet\GreeterClient\bin\Debug>GreeterClient.exe
GreeterClient sending request
GreeterClient received response: Hello Mete - on C#
Press any key to exit...

5. Update the Greeter sample

Let's see what updating our service looks like. Add a new method to our gRPC service called goodbye that returns goodbye instead of hello to the client.

The first step is to update the service definition file greeter.proto.

service GreetingService {
    rpc greeting(HelloRequest) returns (HelloResponse);
    
    rpc goodbye(HelloRequest) returns (HelloResponse);
}

Next, you need to re-generate the client and server stubs. In a command prompt, run generate_protos.bat. Once stubs are generated, you might need to refresh your Visual Studio projects to get the updated code.

Finally, update the client and server code to take advantage of the new method. In the service, update GreeterServiceImpl.cs and add a new goodbye method.

public override Task<HelloResponse> goodbye(HelloRequest request,
       ServerCallContext context)
{
    return Task.FromResult(new HelloResponse { 
          Greeting = "Goodbye " + request.Name });
}

In the client, make a call to the goodbye method in Program.cs.

response = client.goodbye(request);
Console.WriteLine("GreeterClient received response: " 
                       + response.Greeting);

Re-build the project and run the server and client again. You should see client receive a goodbye message now.

> C:\grpc-samples-dotnet\GreeterClient\bin\Debug>GreeterClient.exe
GreeterClient sending request
GreeterClient received response: Hello Mete - on C#
GreeterClient received response: Goodbye Mete - on C#
Press any key to exit...

6. Explore the Chat sample

There is also a ChatServer and a ChatWindowsClient projects in the solution. As the name suggests, this is a client and server pair for a simple chat application. Chat project has the service definition file called chat.proto. It defines a ChatService with a chat method.

service ChatService {
 rpc chat(stream ChatMessage) returns (stream ChatMessageFromServer);
}

The important thing here is that both incoming and outgoing chat messages are marked with the stream keyword. This basically turns the connection into a bidirectional stream where the client and the server can send messages to each other at any time; the perfect solution for a chat application.

You can further explore the sample, build and run it to see how it work as an exercise.

7. Congratulations!

What we've covered

  • The Protocol Buffer Language.
  • How to implement a gRPC service using C#.
  • How to implement a gRPC client using C#.
  • How to update a gRPC service.

Next Steps