gRPC-Web in ASP.NET Core gRPC-Apps

Von James Newton-King

Erfahren Sie, wie Sie einen vorhandenen gRPC-Dienst für ASP.NET Core so konfigurieren, dass er mit dem gRPC-Web-Protokoll von Browser-Apps aus aufgerufen werden können. gRPC-Web erlaubt JavaScript- und Blazor-Apps im Browser, gRPC-Dienste aufzurufen. Es ist nicht möglich, einen HTTP/2-gRPC-Dienst von einer browserbasierten App aus aufzurufen. gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen.

Anweisungen zum Hinzufügen eines gRPC-Diensts zu einer vorhandenen ASP.NET Core-App finden Sie unter Hinzufügen von gRPC-Diensten zu einer ASP.NET Core-App.

Anweisungen zum Erstellen eines gRPC-Projekts finden Sie unter Erstellen eines gRPC-Clients und -Servers in ASP.NET Core.

ASP.NET Core gRPC-Web im Vergleich zu Envoy

Es gibt zwei Möglichkeiten zum Hinzufügen von gRPC-Web zu einer ASP.NET Core-App:

  • Unterstützung von gRPC-Web parallel zu gRPC HTTP/2 in ASP.NET Core. Diese Option verwendet die mit dem Grpc.AspNetCore.Web-Paket bereitgestellte Middleware.
  • Verwenden Sie die gRPC-Webunterstützung des Envoy Proxys, um gRPC-Web in gRPC HTTP/2 zu übersetzen. Der übersetzte Aufruf wird dann an die ASP.NET Core-App weitergeleitet.

Beide Ansätze haben Vor- und Nachteile. Wenn die Umgebung einer App bereits Envoy als Proxy verwendet, kann es sinnvoll sein, Envoy auch zur Bereitstellung von gRPC-Webunterstützung zu verwenden. Als einfache Lösung für gRPC-Web, die nur ASP.NET Core erfordert, ist Grpc.AspNetCore.Web eine gute Wahl.

Konfigurieren von gRPC-Web in ASP.NET Core

gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen. Für gRPC-Web sind keine Änderungen an Diensten erforderlich. Die einzige Änderung besteht im Festlegen der Middleware in Program.cs.

So aktivieren Sie gRPC-Web mit einem ASP.NET Core gRPC-Dienst

  • Fügen Sie einen Verweis auf das Paket Grpc.AspNetCore.Web hinzu.
  • Konfigurieren Sie die App zur Verwendung von gRPC-Web, indem Sie UseGrpcWeb und EnableGrpcWebProgram.cs hinzufügen:
using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb();

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Der vorangehende Code:

  • Fügt die gRPC-Web-Middleware, UseGrpcWeb, nach dem Routing und vor den Endpunkten hinzu.
  • Gibt an, dass die Methode endpoints.MapGrpcService<GreeterService>() gRPC-Web mit EnableGrpcWeb unterstützt.

Alternativ kann die gRPC-Web-Middleware so konfiguriert werden, dass alle Dienste standardmäßig gRPC-Web unterstützen und EnableGrpcWeb nicht erforderlich ist. Geben Sie new GrpcWebOptions { DefaultEnabled = true } an, wenn die Middleware hinzugefügt wird.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Hinweis

Ein bekanntes Problem kann dazu führen, dass ein Fehler auftritt, wenn gRPC-Web in .NET Core 3.x von HTPP.sys gehostet wird.

Eine Problemumgehung, damit gRPC-Web mit HTTP.sys funktioniert, finden Sie unter Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web und CORS

Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung gilt für das Durchführen von gRPC-Webaufrufen mit Browser-Apps. So wird z. B. eine Browser-App, die von https://www.contoso.com versorgt wird, daran gehindert, gRPC-Web-Dienste aufzurufen, die auf https://services.contoso.com gehostet werden. CORS (Cross Origin Resource Sharing) kann verwendet werden, um diese Einschränkung zu lockern.

Damit eine Browser-App die Möglichkeit hat, gRPC-Web-Aufrufe ursprungsübergreifend zu tätigen, richten Sie CORS in ASP.NET Core ein. Verwenden Sie die integrierte CORS-Unterstützung, und machen Sie gRPC-spezifische Header mit WithExposedHeaders verfügbar.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
    builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));

var app = builder.Build();

app.UseGrpcWeb();
app.UseCors();

app.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                    .RequireCors("AllowAll");

app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Der vorangehende Code:

  • Ruft AddCors zum Hinzufügen von CORS-Diensten auf und konfiguriert eine CORS-Richtlinie, die gRPC-spezifische Header verfügbar macht.
  • Ruft UseCors zum Hinzufügen der CORS-Middleware nach der Konfiguration des Routings und vor der Konfiguration von Endpunkten auf.
  • Gibt an, dass die endpoints.MapGrpcService<GreeterService>()-Methode CORS mit RequireCors unterstützt.

gRPC-Web und Streaming

Herkömmliches gRPC über HTTP/2 unterstützt Client-, Server- und bidirektionales Streaming. gRPC-Web bietet eingeschränkte Unterstützung für Streaming:

  • gRPC-Web-Browserclients unterstützen das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden nicht.
  • gRPC-Web-.NET-Clients unterstützen nicht das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden durch HTTP/1.1.
  • ASP.NET Core-gRPC-Dienste, die in Azure App Service und IIS gehostet werden, unterstützen das bidirektionale Streaming nicht.

Bei der Verwendung von gRPC-Web wird nur der Einsatz von unären Methoden und Serverstreamingmethoden empfohlen.

HTTP-Protokoll

Die im . NET SDK enthaltene ASP.NET Core gRPC-Dienstvorlage erstellt eine App, die nur für HTTP/2 konfiguriert ist. Dies ist eine geeignete Standardeinstellung, wenn eine App nur herkömmliches gRPC über HTTP/2 unterstützt. gRPC-Web funktioniert jedoch sowohl mit HTTP/1.1 als auch mit HTTP/2. Einige Plattformen, z. B. UWP oder Unity, können HTTP/2 nicht verwenden. Um alle Client-Apps zu unterstützen, konfigurieren Sie den Server so, dass HTTP/1.1 und HTTP/2 aktiviert sind.

Ändern Sie das Standardprotokoll in appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Alternativ können Sie Kestrel-Endpunkte im Startcode konfigurieren.

Das Aktivieren von HTTP/1.1 und HTTP/2 für denselben Port erfordert TLS für die Protokollaushandlung. Weitere Informationen finden Sie unter ASP.NET Core gRPC: Protokollaushandlung.

Aufrufen von gRPC-Web über den Browser

Browser-Apps können gRPC-Web verwenden, um gRPC-Dienste aufzurufen. Es gibt einige Anforderungen und Einschränkungen beim Aufrufen von gRPC-Diensten mit gRPC-Web aus dem Browser heraus:

  • Der Server muss „configuration“ enthalten, um gRPC-Web zu unterstützen.
  • Clientstreaming und bidirektionale Streamingaufrufe werden nicht unterstützt. Das Serverstreaming wird unterstützt.
  • Das Aufrufen von gRPC-Diensten für eine andere Domäne erfordert die Konfiguration von CORS auf dem Server.

JavaScript gRPC-Web-Client

Es gibt einen JavaScript gRPC-Web-Client. Anweisungen zur Verwendung von gRPC-Web aus JavaScript heraus finden Sie unter Schreiben von JavaScript-Clientcode mit gRPC-Web.

Konfigurieren von gRPC-Web mit dem .NET gRPC-Client

Der .NET gRPC-Client kann für gRPC-Web-Aufrufe konfiguriert werden. Dies ist nützlich für Blazor WebAssembly-Apps, die im Browser gehostet werden und dieselben HTTP-Einschränkungen des JavaScript-Codes aufweisen. Das Aufrufen von gRPC-Web mit einem .NET-Client entspricht dem Aufrufen von HTTP/2 gRPC. Die einzige Änderung besteht darin, wie der Kanal erstellt wird.

So verwenden Sie gRPC-Web

  • Fügen Sie einen Verweis auf das Paket Grpc.Net.Client.Web hinzu.
  • Stellen Sie sicher, dass der Verweis auf das Paket Grpc.Net.Client auf Version 2.29.0 oder höher erfolgt.
  • Konfigurieren Sie den Kanal für die Verwendung von GrpcWebHandler:
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
    HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });

Der vorangehende Code:

  • Konfiguriert einen Kanal zur Verwendung von gRPC-Web.
  • Erstellt einen Client und tätigt einen Aufruf über den Kanal.

GrpcWebHandler hat die folgenden Konfigurationsoptionen:

  • InnerHandlerInnerHandler: Der zugrunde liegende InnerHandler, der die gRPC HTTP-Anforderung stellt, z. B. HttpClientHandler.
  • GrpcWebModeGrpcWebMode: Ein Enumerationstyp, der angibt, ob GrpcWebMode für die gRPC-HTTP-Anforderung application/grpc-web oder application/grpc-web-text lautet.
    • GrpcWebMode.GrpcWeb konfiguriert das Senden von Inhalten ohne Codierung. Standardwert.
    • GrpcWebMode.GrpcWebText konfiguriert Base64-codierte Inhalte. Erforderlich für Serverstreamingaufrufe in Browsern.
  • HttpVersionHttpVersion: Die HttpVersion des HTTP-Protokolls, die verwendet wird, um HttpRequestMessage.VersionHttpRequestMessage.Version für die zugrunde liegende gRPC-HTTP-Anforderung festzulegen. gRPC-Web erfordert keine bestimmte Version und setzt die Standardeinstellung nicht außer Kraft, sofern nicht anders angegeben.

Wichtig

Generierte gRPC-Clients verfügen über synchrone und asynchrone Methoden für den Aufruf unärer Methoden. SayHello ist beispielsweise synchron und SayHelloAsync asynchron. Asynchrone Methoden sind in Blazor WebAssembly stets erforderlich. Der Aufruf einer synchronen Methode in einer Blazor WebAssembly-App führt dazu, dass die App nicht mehr reagiert.

Verwenden der gRPC-Clientfactory mit gRPC-Web

Erstellen Sie unter Verwendung der gRPC-Clientfactory einen mit gRPC-Web kompatiblen .NET-Client:

  • Fügen Sie der Projektdatei Paketverweise für folgende Pakete hinzu:
  • Registrieren Sie einen gRPC-Client mit Dependency Injection (DI), indem Sie die generische Erweiterungsmethode AddGrpcClient verwenden. In einer Blazor WebAssembly-App werden Dienste mit DI in Program.cs registriert.
  • Konfigurieren Sie GrpcWebHandler mithilfe der Erweiterungsmethode ConfigurePrimaryHttpMessageHandler.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Weitere Informationen finden Sie unter gRPC-Clientfactoryintegration in .NET.

Zusätzliche Ressourcen

Erfahren Sie, wie Sie einen vorhandenen gRPC-Dienst für ASP.NET Core so konfigurieren, dass er mit dem gRPC-Web-Protokoll von Browser-Apps aus aufgerufen werden können. gRPC-Web erlaubt JavaScript- und Blazor-Apps im Browser, gRPC-Dienste aufzurufen. Es ist nicht möglich, einen HTTP/2-gRPC-Dienst von einer browserbasierten App aus aufzurufen. gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen.

Anweisungen zum Hinzufügen eines gRPC-Diensts zu einer vorhandenen ASP.NET Core-App finden Sie unter Hinzufügen von gRPC-Diensten zu einer ASP.NET Core-App.

Anweisungen zum Erstellen eines gRPC-Projekts finden Sie unter Erstellen eines gRPC-Clients und -Servers in ASP.NET Core.

ASP.NET Core gRPC-Web im Vergleich zu Envoy

Es gibt zwei Möglichkeiten zum Hinzufügen von gRPC-Web zu einer ASP.NET Core-App:

  • Unterstützung von gRPC-Web parallel zu gRPC HTTP/2 in ASP.NET Core. Diese Option verwendet die mit dem Grpc.AspNetCore.Web-Paket bereitgestellte Middleware.
  • Verwenden Sie die gRPC-Webunterstützung des Envoy Proxys, um gRPC-Web in gRPC HTTP/2 zu übersetzen. Der übersetzte Aufruf wird dann an die ASP.NET Core-App weitergeleitet.

Beide Ansätze haben Vor- und Nachteile. Wenn die Umgebung einer App bereits Envoy als Proxy verwendet, kann es sinnvoll sein, Envoy auch zur Bereitstellung von gRPC-Webunterstützung zu verwenden. Als einfache Lösung für gRPC-Web, die nur ASP.NET Core erfordert, ist Grpc.AspNetCore.Web eine gute Wahl.

Konfigurieren von gRPC-Web in ASP.NET Core

gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen. Für gRPC-Web sind keine Änderungen an Diensten erforderlich. Die einzige Änderung besteht im Festlegen der Middleware in Program.cs.

So aktivieren Sie gRPC-Web mit einem ASP.NET Core gRPC-Dienst

  • Fügen Sie einen Verweis auf das Paket Grpc.AspNetCore.Web hinzu.
  • Konfigurieren Sie die App zur Verwendung von gRPC-Web, indem Sie UseGrpcWeb und EnableGrpcWebProgram.cs hinzufügen:
using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb();

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Der vorangehende Code:

  • Fügt die gRPC-Web-Middleware, UseGrpcWeb, nach dem Routing und vor den Endpunkten hinzu.
  • Gibt an, dass die Methode endpoints.MapGrpcService<GreeterService>() gRPC-Web mit EnableGrpcWeb unterstützt.

Alternativ kann die gRPC-Web-Middleware so konfiguriert werden, dass alle Dienste standardmäßig gRPC-Web unterstützen und EnableGrpcWeb nicht erforderlich ist. Geben Sie new GrpcWebOptions { DefaultEnabled = true } an, wenn die Middleware hinzugefügt wird.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "All gRPC service are supported by default in this example, and are callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Hinweis

Ein bekanntes Problem kann dazu führen, dass ein Fehler auftritt, wenn gRPC-Web in .NET Core 3.x von HTPP.sys gehostet wird.

Eine Problemumgehung, damit gRPC-Web mit HTTP.sys funktioniert, finden Sie unter Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web und CORS

Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung gilt für das Durchführen von gRPC-Webaufrufen mit Browser-Apps. So wird z. B. eine Browser-App, die von https://www.contoso.com versorgt wird, daran gehindert, gRPC-Web-Dienste aufzurufen, die auf https://services.contoso.com gehostet werden. CORS (Cross Origin Resource Sharing) kann verwendet werden, um diese Einschränkung zu lockern.

Damit eine Browser-App die Möglichkeit hat, gRPC-Web-Aufrufe ursprungsübergreifend zu tätigen, richten Sie CORS in ASP.NET Core ein. Verwenden Sie die integrierte CORS-Unterstützung, und machen Sie gRPC-spezifische Header mit WithExposedHeaders verfügbar.

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
    builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));

var app = builder.Build();

app.UseGrpcWeb();
app.UseCors();

app.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                    .RequireCors("AllowAll");

app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS enabled, and is callable from browser apps uisng the gRPC-Web protocal");

app.Run();

Der vorangehende Code:

  • Ruft AddCors zum Hinzufügen von CORS-Diensten auf und konfiguriert eine CORS-Richtlinie, die gRPC-spezifische Header verfügbar macht.
  • Ruft UseCors zum Hinzufügen der CORS-Middleware nach der Konfiguration des Routings und vor der Konfiguration von Endpunkten auf.
  • Gibt an, dass die endpoints.MapGrpcService<GreeterService>()-Methode CORS mit RequireCors unterstützt.

gRPC-Web und Streaming

Herkömmliches gRPC über HTTP/2 unterstützt Client-, Server- und bidirektionales Streaming. gRPC-Web bietet eingeschränkte Unterstützung für Streaming:

  • gRPC-Web-Browserclients unterstützen das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden nicht.
  • gRPC-Web-.NET-Clients unterstützen nicht das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden durch HTTP/1.1.
  • ASP.NET Core-gRPC-Dienste, die in Azure App Service und IIS gehostet werden, unterstützen das bidirektionale Streaming nicht.

Bei der Verwendung von gRPC-Web wird nur der Einsatz von unären Methoden und Serverstreamingmethoden empfohlen.

HTTP-Protokoll

Die im . NET SDK enthaltene ASP.NET Core gRPC-Dienstvorlage erstellt eine App, die nur für HTTP/2 konfiguriert ist. Dies ist eine geeignete Standardeinstellung, wenn eine App nur herkömmliches gRPC über HTTP/2 unterstützt. gRPC-Web funktioniert jedoch sowohl mit HTTP/1.1 als auch mit HTTP/2. Einige Plattformen, z. B. UWP oder Unity, können HTTP/2 nicht verwenden. Um alle Client-Apps zu unterstützen, konfigurieren Sie den Server so, dass HTTP/1.1 und HTTP/2 aktiviert sind.

Ändern Sie das Standardprotokoll in appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Alternativ können Sie Kestrel-Endpunkte im Startcode konfigurieren.

Das Aktivieren von HTTP/1.1 und HTTP/2 für denselben Port erfordert TLS für die Protokollaushandlung. Weitere Informationen finden Sie unter ASP.NET Core gRPC: Protokollaushandlung.

Aufrufen von gRPC-Web über den Browser

Browser-Apps können gRPC-Web verwenden, um gRPC-Dienste aufzurufen. Es gibt einige Anforderungen und Einschränkungen beim Aufrufen von gRPC-Diensten mit gRPC-Web aus dem Browser heraus:

  • Der Server muss „configuration“ enthalten, um gRPC-Web zu unterstützen.
  • Clientstreaming und bidirektionale Streamingaufrufe werden nicht unterstützt. Das Serverstreaming wird unterstützt.
  • Das Aufrufen von gRPC-Diensten für eine andere Domäne erfordert die Konfiguration von CORS auf dem Server.

JavaScript gRPC-Web-Client

Es gibt einen JavaScript gRPC-Web-Client. Anweisungen zur Verwendung von gRPC-Web aus JavaScript heraus finden Sie unter Schreiben von JavaScript-Clientcode mit gRPC-Web.

Konfigurieren von gRPC-Web mit dem .NET gRPC-Client

Der .NET gRPC-Client kann für gRPC-Web-Aufrufe konfiguriert werden. Dies ist nützlich für Blazor WebAssembly-Apps, die im Browser gehostet werden und dieselben HTTP-Einschränkungen des JavaScript-Codes aufweisen. Das Aufrufen von gRPC-Web mit einem .NET-Client entspricht dem Aufrufen von HTTP/2 gRPC. Die einzige Änderung besteht darin, wie der Kanal erstellt wird.

So verwenden Sie gRPC-Web

  • Fügen Sie einen Verweis auf das Paket Grpc.Net.Client.Web hinzu.
  • Stellen Sie sicher, dass der Verweis auf das Paket Grpc.Net.Client auf Version 2.29.0 oder höher erfolgt.
  • Konfigurieren Sie den Kanal für die Verwendung von GrpcWebHandler:
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
    HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });

Der vorangehende Code:

  • Konfiguriert einen Kanal zur Verwendung von gRPC-Web.
  • Erstellt einen Client und tätigt einen Aufruf über den Kanal.

GrpcWebHandler hat die folgenden Konfigurationsoptionen:

  • InnerHandlerInnerHandler: Der zugrunde liegende InnerHandler, der die gRPC HTTP-Anforderung stellt, z. B. HttpClientHandler.
  • GrpcWebModeGrpcWebMode: Ein Enumerationstyp, der angibt, ob GrpcWebMode für die gRPC-HTTP-Anforderung application/grpc-web oder application/grpc-web-text lautet.
    • GrpcWebMode.GrpcWeb konfiguriert das Senden von Inhalten ohne Codierung. Standardwert.
    • GrpcWebMode.GrpcWebText konfiguriert Base64-codierte Inhalte. Erforderlich für Serverstreamingaufrufe in Browsern.
  • HttpVersionHttpVersion: Die HttpVersion des HTTP-Protokolls, die verwendet wird, um HttpRequestMessage.VersionHttpRequestMessage.Version für die zugrunde liegende gRPC-HTTP-Anforderung festzulegen. gRPC-Web erfordert keine bestimmte Version und setzt die Standardeinstellung nicht außer Kraft, sofern nicht anders angegeben.

Wichtig

Generierte gRPC-Clients verfügen über synchrone und asynchrone Methoden für den Aufruf unärer Methoden. SayHello ist beispielsweise synchron und SayHelloAsync asynchron. Asynchrone Methoden sind in Blazor WebAssembly stets erforderlich. Der Aufruf einer synchronen Methode in einer Blazor WebAssembly-App führt dazu, dass die App nicht mehr reagiert.

Verwenden der gRPC-Clientfactory mit gRPC-Web

Erstellen Sie unter Verwendung der gRPC-Clientfactory einen mit gRPC-Web kompatiblen .NET-Client:

  • Fügen Sie der Projektdatei Paketverweise für folgende Pakete hinzu:
  • Registrieren Sie einen gRPC-Client mit Dependency Injection (DI), indem Sie die generische Erweiterungsmethode AddGrpcClient verwenden. In einer Blazor WebAssembly-App werden Dienste mit DI in Program.cs registriert.
  • Konfigurieren Sie GrpcWebHandler mithilfe der Erweiterungsmethode ConfigurePrimaryHttpMessageHandler.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Weitere Informationen finden Sie unter gRPC-Clientfactoryintegration in .NET.

Zusätzliche Ressourcen

Erfahren Sie, wie Sie einen vorhandenen gRPC-Dienst für ASP.NET Core so konfigurieren, dass er mit dem gRPC-Web-Protokoll von Browser-Apps aus aufgerufen werden können. gRPC-Web erlaubt JavaScript- und Blazor-Apps im Browser, gRPC-Dienste aufzurufen. Es ist nicht möglich, einen HTTP/2-gRPC-Dienst von einer browserbasierten App aus aufzurufen. gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen.

Anweisungen zum Hinzufügen eines gRPC-Diensts zu einer vorhandenen ASP.NET Core-App finden Sie unter Hinzufügen von gRPC-Diensten zu einer ASP.NET Core-App.

Anweisungen zum Erstellen eines gRPC-Projekts finden Sie unter Erstellen eines gRPC-Clients und -Servers in ASP.NET Core.

ASP.NET Core gRPC-Web im Vergleich zu Envoy

Es gibt zwei Möglichkeiten zum Hinzufügen von gRPC-Web zu einer ASP.NET Core-App:

  • Unterstützung von gRPC-Web parallel zu gRPC HTTP/2 in ASP.NET Core. Diese Option verwendet die mit dem Grpc.AspNetCore.Web-Paket bereitgestellte Middleware.
  • Verwenden Sie die gRPC-Webunterstützung des Envoy Proxys, um gRPC-Web in gRPC HTTP/2 zu übersetzen. Der übersetzte Aufruf wird dann an die ASP.NET Core-App weitergeleitet.

Beide Ansätze haben Vor- und Nachteile. Wenn die Umgebung einer App bereits Envoy als Proxy verwendet, kann es sinnvoll sein, Envoy auch zur Bereitstellung von gRPC-Webunterstützung zu verwenden. Als einfache Lösung für gRPC-Web, die nur ASP.NET Core erfordert, ist Grpc.AspNetCore.Web eine gute Wahl.

Konfigurieren von gRPC-Web in ASP.NET Core

gRPC-Dienste, die in ASP.NET Core gehostet werden, können so konfiguriert werden, dass sie neben HTTP/2 gRPC auch gRPC-Web unterstützen. Für gRPC-Web sind keine Änderungen an Diensten erforderlich. Die einzige Änderung ist die Startkonfiguration.

So aktivieren Sie gRPC-Web mit einem ASP.NET Core gRPC-Dienst

  • Fügen Sie einen Verweis auf das Paket Grpc.AspNetCore.Web hinzu.
  • Konfigurieren Sie die App zur Verwendung von gRPC-Web, indem Sie UseGrpcWeb und EnableGrpcWebStartup.cs hinzufügen:
public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
    });
}

Der vorangehende Code:

  • Fügt die gRPC-Web-Middleware, UseGrpcWeb, nach dem Routing und vor den Endpunkten hinzu.
  • Gibt an, dass die Methode endpoints.MapGrpcService<GreeterService>() gRPC-Web mit EnableGrpcWeb unterstützt.

Alternativ kann die gRPC-Web-Middleware so konfiguriert werden, dass alle Dienste standardmäßig gRPC-Web unterstützen und EnableGrpcWeb nicht erforderlich ist. Geben Sie new GrpcWebOptions { DefaultEnabled = true } an, wenn die Middleware hinzugefügt wird.

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

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapGrpcService<GreeterService>();
        });
    }
}

Hinweis

Ein bekanntes Problem kann dazu führen, dass ein Fehler auftritt, wenn gRPC-Web in .NET Core 3.x von HTPP.sys gehostet wird.

Eine Problemumgehung, damit gRPC-Web mit HTTP.sys funktioniert, finden Sie unter Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web und CORS

Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat. Diese Einschränkung gilt für das Durchführen von gRPC-Webaufrufen mit Browser-Apps. So wird z. B. eine Browser-App, die von https://www.contoso.com versorgt wird, daran gehindert, gRPC-Web-Dienste aufzurufen, die auf https://services.contoso.com gehostet werden. CORS (Cross Origin Resource Sharing) kann verwendet werden, um diese Einschränkung zu lockern.

Damit eine Browser-App die Möglichkeit hat, gRPC-Web-Aufrufe ursprungsübergreifend zu tätigen, richten Sie CORS in ASP.NET Core ein. Verwenden Sie die integrierte CORS-Unterstützung, und machen Sie gRPC-spezifische Header mit WithExposedHeaders verfügbar.

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

    services.AddCors(o => o.AddPolicy("AllowAll", builder =>
    {
        builder.AllowAnyOrigin()
               .AllowAnyMethod()
               .AllowAnyHeader()
               .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
    }));
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseGrpcWeb();
    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb()
                                                  .RequireCors("AllowAll");
    });
}

Der vorangehende Code:

  • Ruft AddCors zum Hinzufügen von CORS-Diensten auf und konfiguriert eine CORS-Richtlinie, die gRPC-spezifische Header verfügbar macht.
  • Ruft UseCors zum Hinzufügen der CORS-Middleware nach der Konfiguration des Routings und vor der Konfiguration von Endpunkten auf.
  • Gibt an, dass die endpoints.MapGrpcService<GreeterService>()-Methode CORS mit RequireCors unterstützt.

gRPC-Web und Streaming

Herkömmliches gRPC über HTTP/2 unterstützt Client-, Server- und bidirektionales Streaming. gRPC-Web bietet eingeschränkte Unterstützung für Streaming:

  • gRPC-Web-Browserclients unterstützen das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden nicht.
  • gRPC-Web-.NET-Clients unterstützen nicht das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden durch HTTP/1.1.
  • ASP.NET Core-gRPC-Dienste, die in Azure App Service und IIS gehostet werden, unterstützen das bidirektionale Streaming nicht.

Bei der Verwendung von gRPC-Web wird nur der Einsatz von unären Methoden und Serverstreamingmethoden empfohlen.

HTTP-Protokoll

Die im . NET SDK enthaltene ASP.NET Core gRPC-Dienstvorlage erstellt eine App, die nur für HTTP/2 konfiguriert ist. Dies ist eine geeignete Standardeinstellung, wenn eine App nur herkömmliches gRPC über HTTP/2 unterstützt. gRPC-Web funktioniert jedoch sowohl mit HTTP/1.1 als auch mit HTTP/2. Einige Plattformen, z. B. UWP oder Unity, können HTTP/2 nicht verwenden. Um alle Client-Apps zu unterstützen, konfigurieren Sie den Server so, dass HTTP/1.1 und HTTP/2 aktiviert sind.

Ändern Sie das Standardprotokoll in appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Alternativ können Sie Kestrel-Endpunkte im Startcode konfigurieren.

Das Aktivieren von HTTP/1.1 und HTTP/2 für denselben Port erfordert TLS für die Protokollaushandlung. Weitere Informationen finden Sie unter ASP.NET Core gRPC: Protokollaushandlung.

Aufrufen von gRPC-Web über den Browser

Browser-Apps können gRPC-Web verwenden, um gRPC-Dienste aufzurufen. Es gibt einige Anforderungen und Einschränkungen beim Aufrufen von gRPC-Diensten mit gRPC-Web aus dem Browser heraus:

  • Der Server muss „configuration“ enthalten, um gRPC-Web zu unterstützen.
  • Clientstreaming und bidirektionale Streamingaufrufe werden nicht unterstützt. Das Serverstreaming wird unterstützt.
  • Das Aufrufen von gRPC-Diensten für eine andere Domäne erfordert die Konfiguration von CORS auf dem Server.

JavaScript gRPC-Web-Client

Es gibt einen JavaScript gRPC-Web-Client. Anweisungen zur Verwendung von gRPC-Web aus JavaScript heraus finden Sie unter Schreiben von JavaScript-Clientcode mit gRPC-Web.

Konfigurieren von gRPC-Web mit dem .NET gRPC-Client

Der .NET gRPC-Client kann für gRPC-Web-Aufrufe konfiguriert werden. Dies ist nützlich für Blazor WebAssembly-Apps, die im Browser gehostet werden und dieselben HTTP-Einschränkungen des JavaScript-Codes aufweisen. Das Aufrufen von gRPC-Web mit einem .NET-Client entspricht dem Aufrufen von HTTP/2 gRPC. Die einzige Änderung besteht darin, wie der Kanal erstellt wird.

So verwenden Sie gRPC-Web

  • Fügen Sie einen Verweis auf das Paket Grpc.Net.Client.Web hinzu.
  • Stellen Sie sicher, dass der Verweis auf das Paket Grpc.Net.Client auf Version 2.29.0 oder höher erfolgt.
  • Konfigurieren Sie den Kanal für die Verwendung von GrpcWebHandler:
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
    {
        HttpHandler = new GrpcWebHandler(new HttpClientHandler())
    });

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });

Der vorangehende Code:

  • Konfiguriert einen Kanal zur Verwendung von gRPC-Web.
  • Erstellt einen Client und tätigt einen Aufruf über den Kanal.

GrpcWebHandler hat die folgenden Konfigurationsoptionen:

  • InnerHandlerInnerHandler: Der zugrunde liegende InnerHandler, der die gRPC HTTP-Anforderung stellt, z. B. HttpClientHandler.
  • GrpcWebModeGrpcWebMode: Ein Enumerationstyp, der angibt, ob GrpcWebMode für die gRPC-HTTP-Anforderung application/grpc-web oder application/grpc-web-text lautet.
    • GrpcWebMode.GrpcWeb konfiguriert das Senden von Inhalten ohne Codierung. Standardwert.
    • GrpcWebMode.GrpcWebText konfiguriert Base64-codierte Inhalte. Erforderlich für Serverstreamingaufrufe in Browsern.
  • HttpVersionHttpVersion: Die HttpVersion des HTTP-Protokolls, die verwendet wird, um HttpRequestMessage.VersionHttpRequestMessage.Version für die zugrunde liegende gRPC-HTTP-Anforderung festzulegen. gRPC-Web erfordert keine bestimmte Version und setzt die Standardeinstellung nicht außer Kraft, sofern nicht anders angegeben.

Wichtig

Generierte gRPC-Clients verfügen über synchrone und asynchrone Methoden für den Aufruf unärer Methoden. SayHello ist beispielsweise synchron und SayHelloAsync asynchron. Asynchrone Methoden sind in Blazor WebAssembly stets erforderlich. Der Aufruf einer synchronen Methode in einer Blazor WebAssembly-App führt dazu, dass die App nicht mehr reagiert.

Verwenden der gRPC-Clientfactory mit gRPC-Web

Erstellen Sie unter Verwendung der gRPC-Clientfactory einen mit gRPC-Web kompatiblen .NET-Client:

  • Fügen Sie der Projektdatei Paketverweise für folgende Pakete hinzu:
  • Registrieren Sie einen gRPC-Client mit Dependency Injection (DI), indem Sie die generische Erweiterungsmethode AddGrpcClient verwenden. In einer Blazor WebAssembly-App werden Dienste mit DI in Program.cs registriert.
  • Konfigurieren Sie GrpcWebHandler mithilfe der Erweiterungsmethode ConfigurePrimaryHttpMessageHandler.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Weitere Informationen finden Sie unter gRPC-Clientfactoryintegration in .NET.

Zusätzliche Ressourcen