gRPC implementation for .NET and C

The integration of gRPC within the C# and .NET ecosystem has evolved through two distinct phases: the legacy C-core implementation and the modern, native .NET implementation. This evolution reflects the broader progression of the .NET framework itself, specifically the introduction of native HTTP/2 support in .NET Core 3.0 and subsequent versions. For the modern developer, gRPC provides a mechanism to define services and then generate idiomatic client and server stubs across a variety of languages, ensuring that a C# server can seamlessly interact with clients written in other languages, provided they share the same service description.

The Architectural Divide: Grpc.Core vs. grpc-dotnet

The landscape of gRPC for .NET is divided between two primary implementations, distinguished by their underlying architecture and their current support status. Understanding this divide is critical for any engineer deciding which NuGet packages to integrate into their project.

Grpc.Core: The Legacy Implementation

Grpc.Core was the original C# implementation of gRPC, released in 2016. Because .NET did not possess a usable C# HTTP/2 library at the time of its release, this implementation was built upon the native gRPC C core library. This design allowed for cross-platform functionality but introduced a layer of complexity due to its reliance on native binaries.

The supported platforms for Grpc.Core include:
- .NET Core on Linux, Windows, and Mac OS X.
- .NET Framework 4.5+ for Windows environments.
- Mono 4+ across Linux, Windows, and Mac OS X.

From a strategic standpoint, Grpc.Core is now in maintenance mode. In May 2021, gRPC announced the official intention to phase out this implementation. Consequently, it is explicitly recommended that this version should not be used for any new development projects, as it lacks the performance benefits and native integration of the newer stack.

grpc-dotnet: The Modern Standard

Released in September 2019, grpc-dotnet is the current recommended implementation for all .NET/C# development. Unlike its predecessor, it is not based on the gRPC C core native library. Instead, it leverages the native HTTP/2 protocol implementation that was introduced in .NET Core 3 and ASP.NET Core 3.

This shift to a native implementation allows gRPC to integrate more deeply with the .NET ecosystem, offering better performance and easier debugging. The grpc-dotnet implementation is divided into specific NuGet packages based on the role of the application:

  • Grpc.Net.Client: This package is utilized when the application acts as a gRPC client calling other services. It supports gRPC calls over HTTP/2 on .NET Core 3 and .NET 5 or later.
  • Grpc.AspNetCore: This is the framework used for hosting gRPC services. It integrates directly with standard ASP.NET Core features, including dependency injection (DI), logging, authentication, and authorization.

For those using the .NET Framework, it is important to note that support for gRPC over HTTP/2 is limited compared to the robust support found in .NET Core 3 and later.

Tooling and Asset Generation with Grpc.Tools

The transition from a .proto file definition to executable C# code is handled by a specialized tooling package known as Grpc.Tools. This package is a mandatory requirement for both server and client projects to generate the necessary C# assets from the Protocol Buffer definitions.

The behavior of Grpc.Tools is designed to be unobtrusive and efficient. The generated assets are created on an as-needed basis every time the project is built. A critical characteristic of these generated files is that they are not added to the project file nor are they checked into source control. Instead, they exist as build artifacts located within the obj directory.

To control the generation of these assets, the GrpcServices attribute within the reference element can be used to limit what is produced. The available options for GrpcServices are:
- Both: This is the default setting when the attribute is not present.
- Server: Generates only the server-side assets.
- Client: Generates only the client-side assets.
- None: Disables asset generation for that specific reference.

Implementation Frameworks and Package Management

Depending on whether a developer is building a service provider or a service consumer, the required NuGet packages and configuration steps differ.

Server-Side Implementation

For hosting gRPC services, the Grpc.AspNetCore metapackage is the primary tool. This package inherently includes a reference to Grpc.Tools, meaning developers do not need to add the tooling package separately for server projects.

Server projects can be configured by adding the following package reference to the project file:

xml <PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

Alternatively, developers can use the Package Manager within Visual Studio to add Grpc.AspNetCore. By using this framework, the gRPC service is integrated into the ASP.NET Core pipeline, allowing it to benefit from the same middleware, authentication, and authorization logic used by standard Web APIs.

Client-Side Implementation

Client projects require a different approach. They must directly reference Grpc.Tools alongside other necessary packages to facilitate the communication with the gRPC server.

The client implementation typically involves two primary packages:
- Grpc.Net.Client: The core client for .NET Core that builds upon the HttpClient class.
- Grpc.Net.ClientFactory: This provides integration with HttpClientFactory, allowing gRPC clients to be centrally configured and injected into the application using Dependency Injection (DI).

This architecture ensures that clients are managed efficiently, particularly regarding the lifecycle of the underlying HTTP/2 connections.

Development Workflow and Practical Application

Building a gRPC service in C# follows a specific sequence of operations, beginning with the definition of the service contract and ending with the implementation of the logic.

The Contract-First Approach

gRPC employs a contract-first approach to API development. This means the developer first defines the API's structure in a .proto file using Protocol Buffers (protobuf). The .proto file acts as the single source of truth for both the client and the server.

The workflow generally proceeds as follows:
1. Define the service and message types in a .proto file.
2. Use Grpc.Tools to generate the C# stubs.
3. Implement the service logic on the server side by overriding the generated base class.
4. Use the generated client stub to make calls to the server.

Practical Implementation Steps

For developers looking to begin with gRPC in .NET, the most efficient starting point is the gRPC template provided with .NET Core 3.0 or later. This template automates the creation of both a gRPC service website and a corresponding client.

For those wishing to explore existing implementations, the following command can be used to clone the sample repository:

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

After cloning the repository, developers will find a folder named grpc-samples-dotnet containing the GrpcSamples.sln Visual Studio solution. Opening this solution allows for the study of real-world gRPC implementations in C#.

Requirements for Development

To successfully implement a gRPC service using the provided guidelines, the following environment is required:
- A modern web browser, such as Google Chrome or Mozilla Firefox.
- Visual Studio 2013 or a later version.
- A foundational familiarity with the C# language and the .NET Framework.

Comparison of gRPC Implementations for .NET

The following table provides a technical comparison between the two primary C# implementations of gRPC.

Feature Grpc.Core grpc-dotnet
Release Date 2016 September 2019
Base Library C core native library Native .NET / ASP.NET Core
HTTP/2 Support External C library Native .NET Core 3+
Status Maintenance Mode Recommended / Active
Recommended Use Legacy projects only All new development
.NET Core Support Linux, Windows, Mac OS X .NET Core 3, .NET 5+
.NET Framework Support 4.5+ (Windows) Limited HTTP/2 support
Integration Standalone / Native ASP.NET Core DI, Logging, Auth

Technical Analysis of the gRPC Ecosystem

The transition from Grpc.Core to grpc-dotnet is not merely a version update but a fundamental change in how the network stack is handled. The reliance on the C core library in the original implementation created a boundary between the managed .NET code and the unmanaged C code, which often complicated memory management and debugging. By moving the implementation into the native .NET layer via grpc-dotnet, the framework can now leverage the highly optimized HttpClient and the native HTTP/2 capabilities of the Kestrel web server.

The use of Grpc.Net.ClientFactory further enhances this architecture by integrating gRPC with the standard .NET Dependency Injection pattern. This is critical for production-grade applications where the management of connection lifetimes and the reuse of HTTP/2 connections are essential for performance and stability.

The asset generation process via Grpc.Tools ensures that the code remains clean. By placing generated files in the obj directory and treating them as build artifacts, the project structure remains focused on the handwritten business logic rather than the boilerplate code generated from the .proto files. This separation is vital for maintaining clean version control histories, as the generated stubs are automatically recreated based on the .proto definition during every build cycle.

Conclusion

The adoption of gRPC in the .NET ecosystem marks a transition toward high-performance, strongly-typed communication. By utilizing a contract-first design with Protocol Buffers, developers can ensure rigorous API consistency across diverse platforms. The shift from the legacy Grpc.Core to the native grpc-dotnet implementation has unlocked deeper integration with ASP.NET Core, allowing gRPC services to benefit from the full suite of enterprise features such as middleware, dependency injection, and advanced authentication.

The architectural requirement for Grpc.Tools ensures that the translation from IDL to C# is seamless and automated. For modern developers, the path is clear: leverage the Grpc.AspNetCore and Grpc.Net.Client packages within a .NET Core 3.0+ environment to achieve the best possible performance and maintainability. The ability to generate idiomatic stubs means that the complexity of binary serialization and network transport is abstracted away, allowing the engineer to focus on the implementation of the service logic rather than the mechanics of the remote procedure call.

Sources

  1. Google Codelabs - gRPC C#
  2. gRPC.io - C#/.NET Documentation
  3. PeerGroup - gRPC Implementation for .NET/C#
  4. GitHub - grpc-dotnet
  5. Microsoft Learn - gRPC Basics

Related Posts