Building a gRPC Client in .NET
Tags: dotnet, grpc, tutorial, webdev
Published: 2022-03-18 12:17:08

---
title: Building a gRPC Client in .NET
published: true
date: 2022-03-18 12:16:00 UTC
tags: dotnet, grpc, tutorial, webdev
canonical_url: https://sahansera.dev/building-grpc-client-dotnet/
cover_image: https://sahansera.dev/static/8a6fd1782307a629697dfe72cf5e9ec9/dcbba/building-grpc-client-dotnet.webp
---

## Introduction

In this article, we will take a look at how to create a simple gRPC client with .NET and communicate with a server. This is the final post of the blog series where we talk about building gRPC services.

## Motivation

This is the final part of the gRPC articles series. If you didn't catch the previous ones please feel free to do so. The links are down below.

- [Introduction to gRPC](https://sahansera.dev/introduction-to-grpc/)
- [Building a gRPC server with Go](https://sahansera.dev/building-grpc-server-go/)
- [Building a gRPC client with .NET](https://sahansera.dev/building-grpc-server-dotnet/)
- [Building a gRPC client with Go](https://sahansera.dev/building-grpc-client-go)
- [Building a gRPC client with .NET](https://sahansera.dev/building-grpc-client-dotnet) (You are here)

Please note that this is intended for anyone who’s interested in getting started with gRPC. If you’re not, please feel free to skip this article.

## Plan

The plan for this article is as follows.

1. Scaffold a .NET console project.
2. Implementing the gRPC client.
3. Communicating with the server.

In a nutshell, we will be generating the client for the server we built in our previous post.

![building-grpc-client-dotnet-1.png](https://sahansera.dev/static/5981709a41957cdb1d4562a667108034/5a190/building-grpc-client-dotnet-1.png "building-grpc-client-dotnet-1.png")

> 💡  As always, all the code samples documentation can be found at: [https://github.com/sahansera/dotnet-grpc](https://github.com/sahansera/dotnet-grpc)

## Prerequisites

- .NET 6 SDK
- Visual Studio Code or IDE of your choice
- gRPC compiler

Please note that I’m using some of the commands that are macOS specific. Please follow this [link](https://grpc.io/docs/languages/go/quickstart/) to set it up if you are on a different OS.

To install Protobuf compiler:

```sh
brew install protobuf
```

## Project Structure

We can use .NET’s tooling to generate a sample gRPC project. Run the following command at the root of your workspace. Remember how we used `dotnet new grpc` command to scaffold the server project? For this one though, it can simply be a console app.

```sh
dotnet new console -o BookshopClient
```

Your project structure should look like this.

![building-grpc-client-dotnet-2.png](https://sahansera.dev/static/9046d8d539f797996d9ca14be022e291/ea7fb/building-grpc-client-dotnet-2.png "building-grpc-client-dotnet-2.png")

You must be wondering if this is a console app how does it know how to generate the client stubs? Well, it doesn’t. You have to add the following packages to the project first.

```sh
dotnet add BookshopClient.csproj package Grpc.Net.Client
dotnet add BookshopClient.csproj package Google.Protobuf
dotnet add BookshopClient.csproj package Grpc.Tools
```

Once everything’s installed, we can proceed with the rest of the steps.

## Generating the client stubs

We will be using the same Protobuf files that we generated in our previous step. If you haven’t seen that already head over to my previous [post](https://sahansera.dev/building-grpc-server-dotnet/).

Open up the `BookshopClient.csproj` file you need to add the following lines:

```xml
...
<ItemGroup>
  <Protobuf Include="../proto/bookshop.proto" GrpcServices="Client" />
</ItemGroup>
...
```

As you can see we will be reusing our [Bookshop.proto](https://github.com/sahansera/dotnet-grpc/blob/main/Proto/bookshop.proto) file. in this example too. One thing to note here is that we have updated the `GrpcServices` attribute to be `Client`.

## Implementing the gRPC client

Let’s update the Program.cs file to connect to and get the response from the server.

```csharp
using System.Threading.Tasks;
using Grpc.Net.Client;
using Bookshop;

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("http://localhost:5000");
var client = new Inventory.InventoryClient(channel);
var reply = await client.GetBookListAsync(new GetBookListRequest { });

Console.WriteLine("Greeting: " + reply.Books);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
```

This is based on the example given on the Microsoft docs site btw. What I really like about the above code is how easy it is to read. So here’s what happens.

![building-grpc-client-dotnet-3.png](https://sahansera.dev/static/089cb4f9a16aa3be867149f273309c49/5a190/building-grpc-client-dotnet-3.png "building-grpc-client-dotnet-3.png")

1. We first create a gRPC channel with `GrpcChannel.ForAddress` to the server by giving its URI and port. A client can reuse the same channel object to communicate with a gRPC server. This is an expensive operation compared to invoking a gRPC method on the server. You can also pass in a `GrpcChannelOptions` object as the second parameter to define client options. Here’s a [list](https://docs.microsoft.com/en-us/aspnet/core/grpc/configuration?view=aspnetcore-6.0#configure-client-options) for that.
2. Then we use the auto-generated method `Inventory.InventoryClient` by leveraging the channel we created above. One thing to note here is that, if your server has multiple services, you can still use the same `channel` object for all of those.
3. We call the `GetBookListAsync` on our server. By the way, this is a Unary call, we will go through other client-server communication mechanisms in a separate post.
4. Our `GetBookList` method gets called on the server and returns the list of books.

Now that we know how the requests work, let’s see this in action.

## Communicating with the server

Let’s spin up the server that we built in my previous post first. This will be up and running at port `5000`.

```sh
dotnet run --project BookshopServer/BookshopServer.csproj
```

![building-grpc-client-dotnet-4.png](https://sahansera.dev/static/bb98b2bcc1c445963106da33e75e8512/5a190/building-grpc-client-dotnet-4.png "building-grpc-client-dotnet-4.png")

For the client-side, we invoke a similar command.

```sh
dotnet run --project BookshopClient/BookshopClient.csproj
```

And in the terminal, we will get the following outputs.

![building-grpc-client-dotnet-5.png](https://sahansera.dev/static/9da5464a7469cbc83af57113d4e10e3f/5a190/building-grpc-client-dotnet-5.png "building-grpc-client-dotnet-5.png")

Nice! as you can see it’s not that hard to get everything working 🎉 One thing to note is that we left out the details about TLS and different ways to communicate with the server (i.e. Unary, streaming etc.). I will cover such topics in-depth in the future.

## Conclusion

In this article, we looked at how to reuse our Protobuf files to create a client to interact with the server we created in the previous post.

I hope this article series cleared up a lot of confusion that you had about gRPC. Please feel free to share your questions, thoughts, or feedback in the comments section below. Until next time 👋

## References

- [https://docs.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-6.0&tabs=visual-studio-code](https://docs.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-6.0&tabs=visual-studio-code)