Services gRPC avec C#

Ce document décrit les concepts nécessaires pour écrire des applications gRPC en C#. Les sujets abordés ici s’appliquent aux applications gRPC basées sur C-core et ASP.NET Core.

Fichier proto

gRPC utilise une approche de type « Contrat en premier » pour le développement d’API. Les mémoires tampons de protocole (protobuf) sont utilisées comme langage de définition d’interface (IDL) par défaut. Le fichier .proto contient :

  • Définition du service gRPC.
  • Messages envoyés entre les clients et les serveurs.

Pour plus d’informations sur la syntaxe des fichiers protobuf, consultez Créer des messages Protobuf pour les applications .NET.

Par exemple, considérez le fichier greet.proto utilisé dans Prise en main du service gRPC :

  • Définit un service Greeter.
  • Le service Greeter définit un appel SayHello.
  • SayHello envoie un message HelloRequest et reçoit un message HelloReply :
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

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;
}

Si vous souhaitez voir les commentaires de code traduits dans une langue autre que l’anglais, dites-le nous dans cette discussion GitHub.

Ajouter un fichier .proto à une application C#

Le fichier .proto est inclus dans un projet en l’ajoutant au groupe d’éléments <Protobuf> :

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Par défaut, une référence <Protobuf> génère un client concret et une classe de base de service. L’attribut GrpcServices de l’élément de référence peut être utilisé pour limiter la génération de ressources C#. Les options GrpcServices valides sont les suivantes :

  • Both (valeur par défaut lorsqu’elle n’est pas présente)
  • Server
  • Client
  • None

Prise en charge des outils C# pour les fichiers .proto

Le package d’outils Grpc.Tools est requis pour générer les ressources C# à partir de fichiers .proto. Les ressources générées (fichiers) :

  • Sont générées en fonction des besoins chaque fois que le projet est généré.
  • Ne sont pas ajoutées au projet ou archivées dans le contrôle de code source.
  • Sont un artefact de build contenu dans le répertoire obj.

Ce package est requis par les projets serveur et client. Le métapackage Grpc.AspNetCore inclut une référence à Grpc.Tools. Les projets serveur peuvent ajouter Grpc.AspNetCore à l’aide du gestionnaire de package dans Visual Studio ou en ajoutant un <PackageReference> au fichier projet :

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

Les projets client doivent faire directement référence à Grpc.Tools avec les autres packages requis pour utiliser le client gRPC. Le package d’outils n’est pas nécessaire lors de l’exécution. La dépendance est donc marquée avec PrivateAssets="All" :

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

Ressources C# générées

Le package d’outils génère les types C# représentant les messages définis dans les fichiers .proto inclus.

Pour les ressources côté serveur, un type de base de service abstrait est généré. Le type de base contient les définitions de tous les appels gRPC contenus dans le fichier .proto. Créez une implémentation de service concrète qui dérive de ce type de base et implémente la logique pour les appels gRPC. Pour greet.proto, l’exemple décrit précédemment, un type GreeterBase abstrait qui contient une méthode SayHello virtuelle est généré. Une implémentation concrète GreeterService remplace la méthode et implémente la logique qui gère l’appel gRPC.

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
        });
    }
}

Pour les ressources côté client, un type de client concret est généré. Les appels gRPC dans le fichier .proto sont traduits en méthodes sur le type concret, qui peuvent être appelées. Pour greet.proto, l’exemple décrit précédemment, un type GreeterClient concret est généré. Appelez GreeterClient.SayHelloAsync pour lancer un appel gRPC au serveur.

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

Par défaut, les ressources serveur et client sont générées pour chaque fichier .proto inclus dans le groupe d’éléments <Protobuf>. Pour garantir que seules les ressources serveur sont générées dans un projet de serveur, l’attribut GrpcServices est défini sur Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

De même, l’attribut est défini sur Client dans les projets clients.

Ressources supplémentaires

Ce document décrit les concepts nécessaires pour écrire des applications gRPC en C#. Les sujets abordés ici s’appliquent aux applications gRPC basées sur C-core et ASP.NET Core.

Fichier proto

gRPC utilise une approche de type « Contrat en premier » pour le développement d’API. Les mémoires tampons de protocole (protobuf) sont utilisées comme langage de définition d’interface (IDL) par défaut. Le fichier .proto contient :

  • Définition du service gRPC.
  • Messages envoyés entre les clients et les serveurs.

Pour plus d’informations sur la syntaxe des fichiers protobuf, consultez Créer des messages Protobuf pour les applications .NET.

Par exemple, considérez le fichier greet.proto utilisé dans Prise en main du service gRPC :

  • Définit un service Greeter.
  • Le service Greeter définit un appel SayHello.
  • SayHello envoie un message HelloRequest et reçoit un message HelloReply :
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

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;
}

Si vous souhaitez voir les commentaires de code traduits dans une langue autre que l’anglais, dites-le nous dans cette discussion GitHub.

Ajouter un fichier .proto à une application C#

Le fichier .proto est inclus dans un projet en l’ajoutant au groupe d’éléments <Protobuf> :

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Par défaut, une référence <Protobuf> génère un client concret et une classe de base de service. L’attribut GrpcServices de l’élément de référence peut être utilisé pour limiter la génération de ressources C#. Les options GrpcServices valides sont les suivantes :

  • Both (valeur par défaut lorsqu’elle n’est pas présente)
  • Server
  • Client
  • None

Prise en charge des outils C# pour les fichiers .proto

Le package d’outils Grpc.Tools est requis pour générer les ressources C# à partir de fichiers .proto. Les ressources générées (fichiers) :

  • Sont générées en fonction des besoins chaque fois que le projet est généré.
  • Ne sont pas ajoutées au projet ou archivées dans le contrôle de code source.
  • Sont un artefact de build contenu dans le répertoire obj.

Ce package est requis par les projets serveur et client. Le métapackage Grpc.AspNetCore inclut une référence à Grpc.Tools. Les projets serveur peuvent ajouter Grpc.AspNetCore à l’aide du gestionnaire de package dans Visual Studio ou en ajoutant un <PackageReference> au fichier projet :

<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />

Les projets client doivent faire directement référence à Grpc.Tools avec les autres packages requis pour utiliser le client gRPC. Le package d’outils n’est pas nécessaire lors de l’exécution. La dépendance est donc marquée avec PrivateAssets="All" :

<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Ressources C# générées

Le package d’outils génère les types C# représentant les messages définis dans les fichiers .proto inclus.

Pour les ressources côté serveur, un type de base de service abstrait est généré. Le type de base contient les définitions de tous les appels gRPC contenus dans le fichier .proto. Créez une implémentation de service concrète qui dérive de ce type de base et implémente la logique pour les appels gRPC. Pour greet.proto, l’exemple décrit précédemment, un type GreeterBase abstrait qui contient une méthode SayHello virtuelle est généré. Une implémentation concrète GreeterService remplace la méthode et implémente la logique qui gère l’appel gRPC.

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
        });
    }
}

Pour les ressources côté client, un type de client concret est généré. Les appels gRPC dans le fichier .proto sont traduits en méthodes sur le type concret, qui peuvent être appelées. Pour greet.proto, l’exemple décrit précédemment, un type GreeterClient concret est généré. Appelez GreeterClient.SayHelloAsync pour lancer un appel gRPC au serveur.

static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

Par défaut, les ressources serveur et client sont générées pour chaque fichier .proto inclus dans le groupe d’éléments <Protobuf>. Pour garantir que seules les ressources serveur sont générées dans un projet de serveur, l’attribut GrpcServices est défini sur Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

De même, l’attribut est défini sur Client dans les projets clients.

Ressources supplémentaires