An Introduction to gRPC in .NET

A developer's guide to gRPC, the modern, high-performance RPC framework. Learn how to build a simple gRPC service in ASP.NET Core, define a service with Protocol Buffers, and see how it compares to REST.

For years, REST over HTTP/1.1 has been the de facto standard for building APIs, especially for communication between microservices. However, a newer, high-performance alternative has been gaining massive traction: gRPC.

gRPC is a modern, open-source, high-performance Remote Procedure Call (RPC) framework that can run in any environment. It was originally developed by Google and is now part of the Cloud Native Computing Foundation (CNCF). With first-class support built into ASP.NET Core, gRPC is now a compelling choice for .NET developers building microservices.

What is gRPC?

At its core, gRPC allows a client application to directly call a method on a server application on a different machine as if it were a local object. This makes it easier to create distributed applications and services.

Key features of gRPC include:

  • High Performance: gRPC is built on top of HTTP/2, which is significantly more efficient than HTTP/1.1. It uses features like multiplexing and server push to reduce latency.
  • Contract-First API Development: gRPC uses Protocol Buffers (Protobuf) to define the service contract. This contract defines the services and the messages in a strongly-typed, language-agnostic way.
  • Efficient Binary Serialization: Protobuf serializes messages into a compact binary format, which is much smaller and faster to parse than text-based formats like JSON.
  • Streaming: gRPC supports four types of streaming: unary (a simple request/response), server streaming, client streaming, and bi-directional streaming.

Defining a Service with Protocol Buffers

With gRPC, you start by defining your service in a .proto file. This file is the single source of truth for your service contract.

Let's define a simple Greeter service.

greet.proto

syntax = "proto3";

package greet;

// The greeting service definition.
service Greeter {
  // Sends 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 {
  string message = 1;
}

From this .proto file, the gRPC tooling can automatically generate the server-side base classes and the client-side stubs in your chosen language (in this case, C#).

Building a gRPC Service in ASP.NET Core

Creating a gRPC service in ASP.NET Core is incredibly simple with the built-in templates.

1. Create the Project

dotnet new grpc -n MyGrpcService

2. Implement the Service

The tooling will generate a GreeterService base class from your .proto file. You then create a class that inherits from it and overrides the methods.

// Services/GreeterService.cs
public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

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

3. Configure the Service

In your Startup.cs, you register the gRPC service and map the service endpoint.

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>();
    });
}

gRPC vs. REST

So when should you choose gRPC over REST?

  • Use gRPC for:

    • Internal, service-to-service communication: This is the sweet spot for gRPC. The high performance and strongly-typed contracts are perfect for communication between microservices.
    • Streaming scenarios: If you need to stream data between services, gRPC's built-in streaming support is far superior to what you can achieve with REST.
    • Polyglot environments: When you have services written in multiple different languages, the contract-first approach of Protobuf makes integration easy.
  • Use REST for:

    • Browser-facing APIs: gRPC is not well-supported in browsers without a proxy (gRPC-Web). REST with JSON is the standard for APIs that need to be called directly from a web browser.
    • Simple request/response APIs: For simple APIs where the performance overhead of JSON is not a concern, REST is often simpler to get started with.

Conclusion

gRPC is a powerful and modern framework for building high-performance, distributed applications. With its first-class support in .NET, it provides a compelling alternative to REST for backend communication. By leveraging HTTP/2 and Protocol Buffers, gRPC enables you to build services that are faster, more efficient, and more robust, making it an essential tool for any .NET developer building microservices.