gRPC-Dienste mit C#

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Warnung

Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der Supportrichtlinie für .NET und .NET Core. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

In diesem Artikel werden die Konzepte erläutert, die zum Schreiben von gRPC-Apps in C# erforderlich sind. Die hier behandelten Themen gelten für gRPC-Apps, die auf C-Core und auf ASP.NET Core basieren.

PROTO-Datei

gRPC verwendet einen Vertrag zuerst-Ansatz für die API-Entwicklung. Protokollpuffer (protobuf) werden standardmäßig als IDL (Interface Definition Language) verwendet. Die Datei .proto enthält Folgendes:

  • Die Definition des gRPC-Diensts
  • Die zwischen Clients und Servern übermittelten Nachrichten

Weitere Informationen zur Syntax von Protobuf-Dateien finden Sie unter Erstellen von Protobuf-Nachrichten für .NET-Apps.

Sehen Sie sich beispielsweise die Datei greet.proto an, die in den ersten Schritten mit dem gRPC-Dienst verwendet wird:

  • Die Datei definiert einen Greeter-Dienst.
  • Der Greeter-Dienst definiert einen SayHello-Aufruf.
  • SayHello sendet eine HelloRequest-Nachricht und empfängt eine HelloReply-Nachricht:
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;
}

Wenn Sie möchten, dass Codekommentare in anderen Sprachen als Englisch angezeigt werden, informieren Sie uns in diesem GitHub-Issue.

Hinzufügen einer .proto-Datei zu einer C#-App

Die .proto-Datei wird in ein Projekt eingefügt, indem sie zur Elementgruppe <Protobuf> hinzugefügt wird:

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

Durch einen <Protobuf>-Verweis werden standardmäßig ein konkreter Client und eine Dienstbasisklasse generiert. Mit dem Attribut GrpcServices des Verweiselements kann das Generieren von C#-Objekten beschränkt werden. Gültige Optionen für GrpcServices sind:

  • Both (Standardwert, wenn nicht vorhanden)
  • Server
  • Client
  • None

C#-Toolunterstützung für .proto-Dateien

Das Toolpaket Grpc.Tools ist zum Generieren der C#-Ressourcen aus .proto-Dateien erforderlich. Die generierten Ressourcen (Dateien):

  • Werden jedes Mal nach Bedarf generiert, wenn der Buildvorgang für das Projekt ausgeführt wird.
  • Werden nicht zum Projekt hinzugefügt oder in der Quellcodeverwaltung eingecheckt.
  • Sind Buildartefakte, die im obj-Verzeichnis enthalten sind.

Dieses Paket ist für die Server- und Clientprojekte erforderlich. Das Metapaket Grpc.AspNetCore enthält einen Verweis auf Grpc.Tools. Serverprojekte können Grpc.AspNetCore mithilfe des Paket-Managers in Visual Studio oder durch Hinzufügen von <PackageReference> zur Projektdatei hinzufügen:

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

Clientprojekte sollten direkt auf Grpc.Tools sowie auf die anderen zum Verwenden des gRPC-Clients erforderlichen Pakete verweisen. Das Toolpaket ist nicht zur Laufzeit erforderlich, darum ist die Abhängigkeit mit PrivateAssets="All" markiert:

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

Generierte C#-Ressourcen

Das Toolpaket generiert die C#-Typen, die die Nachrichten darstellen, die in den enthaltenen .proto-Dateien definiert werden.

Für serverseitige Ressourcen wird ein abstrakter Dienstbasistyp generiert. Der Basistyp enthält die Definitionen für alle gRPC-Aufrufe, die in der .proto-Datei enthalten sind. Erstellen Sie eine konkrete Dienstimplementierung, die von diesem Basistyp abgeleitet wird und die Logik für die gRPC-Aufrufe implementiert. Für das zuvor beschriebene Beispiel greet.proto wird ein abstrakter GreeterBase-Typ generiert, der eine virtuelle SayHello-Methode enthält. Eine konkrete GreeterService-Implementierung überschreibt die Methode und implementiert die Logik, die den gRPC-Aufruf verarbeitet.

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

Für clientseitige Ressourcen wird ein konkreter Clienttyp generiert. Die gRPC-Aufrufe in der .proto-Datei werden in Methoden für den konkreten Typ übersetzt, die aufgerufen werden können. Für das zuvor beschriebene Beispiel greet.proto wird ein konkreter GreeterClient-Typ generiert. Rufen Sie GreeterClient.SayHelloAsync auf, um einen gRPC-Aufruf an den Server zu initiieren.

// 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();

Server- und Clientressourcen werden standardmäßig für alle .proto-Dateien generiert, die in der Elementgruppe <Protobuf> enthalten sind. Das GrpcServices-Attribut wird auf Server festgelegt, um sicherzustellen, dass nur die Serverressourcen in einem Serverprojekt generiert werden.

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

Entsprechend wird das Attribut bei Clientprojekten auf Client festgelegt.

Zusätzliche Ressourcen

In diesem Artikel werden die Konzepte erläutert, die zum Schreiben von gRPC-Apps in C# erforderlich sind. Die hier behandelten Themen gelten für gRPC-Apps, die auf C-Core und auf ASP.NET Core basieren.

PROTO-Datei

gRPC verwendet einen Vertrag zuerst-Ansatz für die API-Entwicklung. Protokollpuffer (protobuf) werden standardmäßig als IDL (Interface Definition Language) verwendet. Die Datei .proto enthält Folgendes:

  • Die Definition des gRPC-Diensts
  • Die zwischen Clients und Servern übermittelten Nachrichten

Weitere Informationen zur Syntax von Protobuf-Dateien finden Sie unter Erstellen von Protobuf-Nachrichten für .NET-Apps.

Sehen Sie sich beispielsweise die Datei greet.proto an, die in den ersten Schritten mit dem gRPC-Dienst verwendet wird:

  • Die Datei definiert einen Greeter-Dienst.
  • Der Greeter-Dienst definiert einen SayHello-Aufruf.
  • SayHello sendet eine HelloRequest-Nachricht und empfängt eine HelloReply-Nachricht:
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;
}

Wenn Sie möchten, dass Codekommentare in anderen Sprachen als Englisch angezeigt werden, informieren Sie uns in diesem GitHub-Issue.

Hinzufügen einer .proto-Datei zu einer C#-App

Die .proto-Datei wird in ein Projekt eingefügt, indem sie zur Elementgruppe <Protobuf> hinzugefügt wird:

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

Durch einen <Protobuf>-Verweis werden standardmäßig ein konkreter Client und eine Dienstbasisklasse generiert. Mit dem Attribut GrpcServices des Verweiselements kann das Generieren von C#-Objekten beschränkt werden. Gültige Optionen für GrpcServices sind:

  • Both (Standardwert, wenn nicht vorhanden)
  • Server
  • Client
  • None

C#-Toolunterstützung für .proto-Dateien

Das Toolpaket Grpc.Tools ist zum Generieren der C#-Ressourcen aus .proto-Dateien erforderlich. Die generierten Ressourcen (Dateien):

  • Werden jedes Mal nach Bedarf generiert, wenn der Buildvorgang für das Projekt ausgeführt wird.
  • Werden nicht zum Projekt hinzugefügt oder in der Quellcodeverwaltung eingecheckt.
  • Sind Buildartefakte, die im obj-Verzeichnis enthalten sind.

Dieses Paket ist für die Server- und Clientprojekte erforderlich. Das Metapaket Grpc.AspNetCore enthält einen Verweis auf Grpc.Tools. Serverprojekte können Grpc.AspNetCore mithilfe des Paket-Managers in Visual Studio oder durch Hinzufügen von <PackageReference> zur Projektdatei hinzufügen:

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

Clientprojekte sollten direkt auf Grpc.Tools sowie auf die anderen zum Verwenden des gRPC-Clients erforderlichen Pakete verweisen. Das Toolpaket ist nicht zur Laufzeit erforderlich, darum ist die Abhängigkeit mit PrivateAssets="All" markiert:

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

Generierte C#-Ressourcen

Das Toolpaket generiert die C#-Typen, die die Nachrichten darstellen, die in den enthaltenen .proto-Dateien definiert werden.

Für serverseitige Ressourcen wird ein abstrakter Dienstbasistyp generiert. Der Basistyp enthält die Definitionen für alle gRPC-Aufrufe, die in der .proto-Datei enthalten sind. Erstellen Sie eine konkrete Dienstimplementierung, die von diesem Basistyp abgeleitet wird und die Logik für die gRPC-Aufrufe implementiert. Für das zuvor beschriebene Beispiel greet.proto wird ein abstrakter GreeterBase-Typ generiert, der eine virtuelle SayHello-Methode enthält. Eine konkrete GreeterService-Implementierung überschreibt die Methode und implementiert die Logik, die den gRPC-Aufruf verarbeitet.

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

Für clientseitige Ressourcen wird ein konkreter Clienttyp generiert. Die gRPC-Aufrufe in der .proto-Datei werden in Methoden für den konkreten Typ übersetzt, die aufgerufen werden können. Für das zuvor beschriebene Beispiel greet.proto wird ein konkreter GreeterClient-Typ generiert. Rufen Sie GreeterClient.SayHelloAsync auf, um einen gRPC-Aufruf an den Server zu initiieren.

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

Server- und Clientressourcen werden standardmäßig für alle .proto-Dateien generiert, die in der Elementgruppe <Protobuf> enthalten sind. Das GrpcServices-Attribut wird auf Server festgelegt, um sicherzustellen, dass nur die Serverressourcen in einem Serverprojekt generiert werden.

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

Entsprechend wird das Attribut bei Clientprojekten auf Client festgelegt.

Zusätzliche Ressourcen