# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/grpc/csharp.md

---
slug: grpc-csharp
title: gRPC protoc C# Client
---

[![](/img/pages/grpc/csharp.png)](https://youtu.be/0TXk9y24NIw)

::: info YouTube
YouTube: [youtu.be/0TXk9y24NIw](https://youtu.be/0TXk9y24NIw)
:::

## C# protoc generated GrpcServiceClient TodoWorld Example

Install [x dotnet tool](/dotnet-tool):
    
:::sh
dotnet tool install --global x 
:::

Create a new C# Console App:

:::sh
dotnet new console
:::

Add required NuGet Packages:

:::sh
dotnet add package Google.Protobuf ServiceStack.GrpcClient
:::
    
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:

:::sh
$ x get https://todoworld.servicestack.net/grpc.crt 
:::

Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient:

:::sh
x proto-csharp https://todoworld.servicestack.net
:::
    
Use protoc generated DTOs and  `GrpcServiceClient` to call TodoWorld gRPC Service:

### C# smart gRPC GrpcServicesClient Example

The smart client registers a ServiceStack Interceptor to enable the richer integration features in ServiceStack
Services as found in ServiceStack's Generic `GrpcServiceClient` above, including detailed structured Exception handling,
built-in JWT, Session, Credentials Auth support, 
[Automatically refreshing Access Tokens](/auth/jwt-authprovider#automatically-refreshing-access-tokens), etc.

This ServiceStack Interceptor can be registered using `GrpcServiceStack.Client()`  when creating the protoc `GrpcServicesClient`:

```csharp
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using ServiceStack;

namespace TodoWorld
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var client = new GrpcServices.GrpcServicesClient(
                GrpcServiceStack.Client("https://todoworld.servicestack.net:50051", 
                    new X509Certificate2("grpc.crt"),
                    GrpcUtils.AllowSelfSignedCertificatesFrom("todoworld.servicestack.net")));

            var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });

            Console.WriteLine(response.Result);
        }
    }
}
```

Override `Program.cs` with the above C# Example: 

:::sh
npx add-in todoworld-csharp-smart
:::

Run example:

:::sh
dotnet run
:::

### protoc-only generated Service Client

Alternatively clients can opt to use the vanilla protoc generated ServiceClient without any dependency to 
**ServiceStack.GrpcClient** which will fallback to gRPC's default behavior of basic error handling with any
auth headers needing to be populated manually.

Add required core package dependencies:

:::sh
dotnet add package Grpc.Core Grpc.Net.Client
:::

### C# protoc gRPC insecure Example

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

namespace TodoWorld
{
    class Program
    {
        static async Task Main(string[] args)
        {
            AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
            var client = new GrpcServices.GrpcServicesClient(
                GrpcChannel.ForAddress("http://todoworld.servicestack.net:5054"));

            var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });

            Console.WriteLine(response.Result);
        }
    }
}
```

Override `Program.cs` with the above C# Example: 

:::sh
npx add-in todoworld-csharp
:::

Run example:

:::sh
dotnet run
:::

### C# protoc gRPC SSL Example

```csharp
using System;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;

namespace TodoWorld
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var client = new GrpcServices.GrpcServicesClient(
                GrpcChannel.ForAddress("https://todoworld.servicestack.net:50051", new GrpcChannelOptions {
                    HttpClient = new System.Net.Http.HttpClient(new System.Net.Http.HttpClientHandler {
                        ClientCertificates = { new X509Certificate2("grpc.crt") },
                        ServerCertificateCustomValidationCallback = (req, cert, certChain, sslErrors) =>
                            cert.SubjectName.RawData.SequenceEqual(cert.IssuerName.RawData) && // self-signed
                            cert.GetNameInfo(X509NameType.DnsName, forIssuer:false) == "todoworld.servicestack.net" &&
                            (sslErrors & ~sslErrors.RemoteCertificateChainErrors) == sslErrors.None // only this
                    })
                }));

            var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });

            Console.WriteLine(response.Result);
        }
    }
}
```

Override `Program.cs` with the above C# Example: 

:::sh
npx add-in todoworld-csharp-ssl
:::

Run example:

:::sh
dotnet run
:::

### C# Local Development gRPC SSL CRUD Example

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

namespace CSharp
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            // Certificate registration not required when using trusted local development certificate  
            var client = new GrpcServices.GrpcServicesClient(GrpcChannel.ForAddress("https://localhost:5001"));
            await client.PostResetTodosAsync(new ResetTodos());

            //POST /todos
            var todo = (await client.PostCreateTodoAsync(new CreateTodo { Title = "ServiceStack" })).Result;
            Console.WriteLine($"new todo Id: {todo.Id}, Title: {todo.Title}");
            
            //GET /todos
            var all = await client.CallGetTodosAsync(new GetTodos());
            Console.WriteLine($"todos: {all.Results?.Count ?? 0}");

            //GET /todos/1
            todo = (await client.CallGetTodoAsync(new GetTodo { Id = todo.Id })).Result;
            Console.WriteLine($"get todo Id: {todo.Id}, Title: {todo.Title}");

            //GET /todos
            all = await client.CallGetTodosAsync(new GetTodos());
            Console.WriteLine($"todos: {all.Results?.Count ?? 0}");

            //PUT /todos/1
            await client.PutUpdateTodoAsync(new UpdateTodo { Id = todo.Id, Title = "gRPC" });

            //GET /todos/1
            todo = (await client.CallGetTodoAsync(new GetTodo { Id = todo.Id })).Result;
            Console.WriteLine($"updated todo Title: {todo.Title}");

            //DELETE /todos/1
            await client.CallDeleteTodoAsync(new DeleteTodo { Id = todo.Id });

            //GET /todos
            all = await client.CallGetTodosAsync(new GetTodos());
            Console.WriteLine($"todos: {all.Results?.Count ?? 0}");
        }
    }
}
```

Refer to [/clients/csharp](https://github.com/NetCoreApps/todo-world/tree/master/clients/csharp)
for a complete example project.

### More Examples

For more protoc generated `GrpcServices.GrpcServiceClient` examples check out the unit tests at:

 - [ProtocTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Extensions.Tests/Protoc/ProtocTests.cs)
 - [ProtocTodoTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Extensions.Tests/Protoc/ProtocTodoTests.cs)
 - [ProtocAuthTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Extensions.Tests/Protoc/ProtocAuthTests.cs)
 - [ProtocServerEventsTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Extensions.Tests/Protoc/ProtocServerEventsTests.cs)
 - [ProtocDynamicAutoQueryTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Extensions.Tests/Protoc/ProtocDynamicAutoQueryTests.cs)