Verwenden von gRPC in Browser-AppsUse gRPC in browser apps

Von James Newton-KingBy 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.Learn how to configure an existing ASP.NET Core gRPC service to be callable from browser apps, using the gRPC-Web protocol. gRPC-Web erlaubt JavaScript- und Blazor-Apps im Browser, gRPC-Dienste aufzurufen.gRPC-Web allows browser JavaScript and Blazor apps to call gRPC services. Es ist nicht möglich, einen HTTP/2-gRPC-Dienst von einer browserbasierten App aus aufzurufen.It's not possible to call an HTTP/2 gRPC service from a browser-based app. 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.gRPC services hosted in ASP.NET Core can be configured to support gRPC-Web alongside HTTP/2 gRPC.

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.For instructions on adding a gRPC service to an existing ASP.NET Core app, see Add gRPC services to an ASP.NET Core app.

Anweisungen zum Erstellen eines gRPC-Projekts finden Sie unter Erstellen eines .NET Core-gRPC-Clients und -Servers in ASP.NET Core.For instructions on creating a gRPC project, see Erstellen eines .NET Core-gRPC-Clients und -Servers in ASP.NET Core.

gRPC-Web in ASP.NET Core im Vergleich zu EnvoygRPC-Web in ASP.NET Core vs. Envoy

Es gibt zwei Möglichkeiten zum Hinzufügen von gRPC-Web zu einer ASP.NET Core-App:There are two choices for how to add gRPC-Web to an ASP.NET Core app:

  • Unterstützung von gRPC-Web parallel zu gRPC HTTP/2 in ASP.NET Core.Support gRPC-Web alongside gRPC HTTP/2 in ASP.NET Core. Diese Option verwendet die mit dem Grpc.AspNetCore.Web-Paket bereitgestellte Middleware.This option uses middleware provided by the Grpc.AspNetCore.Web package.
  • Verwenden Sie die gRPC-Webunterstützung des Envoy Proxys, um gRPC-Web in gRPC HTTP/2 zu übersetzen.Use the Envoy proxy's gRPC-Web support to translate gRPC-Web to gRPC HTTP/2. Der übersetzte Aufruf wird dann an die ASP.NET Core-App weitergeleitet.The translated call is then forwarded onto the ASP.NET Core app.

Beide Ansätze haben Vor- und Nachteile.There are pros and cons to each approach. Wenn die Umgebung einer App bereits Envoy als Proxy verwendet, kann es sinnvoll sein, Envoy auch zur Bereitstellung von gRPC-Webunterstützung zu verwenden.If an app's environment is already using Envoy as a proxy, it might make sense to also use Envoy to provide gRPC-Web support. Als einfache Lösung für gRPC-Web, die nur ASP.NET Core erfordert, ist Grpc.AspNetCore.Web eine gute Wahl.For a basic solution for gRPC-Web that only requires ASP.NET Core, Grpc.AspNetCore.Web is a good choice.

Konfigurieren von gRPC-Web in ASP.NET CoreConfigure 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.gRPC services hosted in ASP.NET Core can be configured to support gRPC-Web alongside HTTP/2 gRPC. Für gRPC-Web sind keine Änderungen der Dienste erforderlich.gRPC-Web does not require any changes to services. Die einzige Änderung ist die Startkonfiguration.The only modification is startup configuration.

So aktivieren Sie gRPC-Web mit einem ASP.NET Core gRPC-DienstTo enable gRPC-Web with an ASP.NET Core gRPC service:

  • Fügen Sie einen Verweis auf das Paket Grpc.AspNetCore.Web hinzu.Add a reference to the Grpc.AspNetCore.Web package.
  • Konfigurieren Sie die App zur Verwendung von gRPC-Web, indem Sie UseGrpcWeb und EnableGrpcWeb zu Startup.cs hinzufügen:Configure the app to use gRPC-Web by adding UseGrpcWeb and EnableGrpcWeb to Startup.cs:
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:The preceding code:

  • Fügt die gRPC-Web-Middleware, UseGrpcWeb, nach dem Routing und vor den Endpunkten hinzu.Adds the gRPC-Web middleware, UseGrpcWeb, after routing and before endpoints.
  • Gibt die Methode endpoints.MapGrpcService<GreeterService>() an, die gRPC-Web mit EnableGrpcWeb unterstützt.Specifies the endpoints.MapGrpcService<GreeterService>() method supports gRPC-Web with EnableGrpcWeb.

Alternativ kann die gRPC-Web-Middleware so konfiguriert werden, dass alle Dienste standardmäßig gRPC-Web unterstützen und EnableGrpcWeb nicht erforderlich ist.Alternatively, the gRPC-Web middleware can be configured so all services support gRPC-Web by default and EnableGrpcWeb isn't required. Geben Sie new GrpcWebOptions { DefaultEnabled = true } an, wenn die Middleware hinzugefügt wird.Specify new GrpcWebOptions { DefaultEnabled = true } when the middleware is added.

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

Es gibt ein bekanntes Problem, das dazu führen kann, dass gRPC-Web fehlschlägt, wenn es von Htpp.sys in .NET Core 3.x gehostet wird.There is a known issue that causes gRPC-Web to fail when hosted by Http.sys in .NET Core 3.x.

Eine Problemumgehung, um gRPC-Web auf Http.sys betreiben zu können, finden Sie hier.A workaround to get gRPC-Web working on Http.sys is available here.

gRPC-Web und CORSgRPC-Web and CORS

Die Browsersicherheit verhindert, dass eine Webseite Anforderungen an eine andere Domäne als diejenige stellt, die die Webseite versorgt hat.Browser security prevents a web page from making requests to a different domain than the one that served the web page. Diese Einschränkung gilt für das Durchführen von gRPC-Webaufrufen mit Browser-Apps.This restriction applies to making gRPC-Web calls with 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.For example, a browser app served by https://www.contoso.com is blocked from calling gRPC-Web services hosted on https://services.contoso.com. Die Ressourcenfreigabe zwischen verschiedenen Ursprüngen (Cross Origin Resource Sharing, CORS) kann verwendet werden, um diese Einschränkung zu lockern.Cross Origin Resource Sharing (CORS) can be used to relax this restriction.

Damit eine Browser-App die Möglichkeit hat, gRPC-Web-Aufrufe ursprungsübergreifend zu tätigen, richten Sie CORS in ASP.NET Core ein.To allow a browser app to make cross-origin gRPC-Web calls, set up CORS in ASP.NET Core. Verwenden Sie die integrierte CORS-Unterstützung, und machen Sie gRPC-spezifische Header mit WithExposedHeaders verfügbar.Use the built-in CORS support, and expose gRPC-specific headers with WithExposedHeaders.

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:The preceding code:

  • Ruft AddCors zum Hinzufügen von CORS-Diensten auf und konfiguriert eine CORS-Richtlinie, die gRPC-spezifische Header verfügbar macht.Calls AddCors to add CORS services and configures a CORS policy that exposes gRPC-specific headers.
  • Ruft UseCors zum Hinzufügen der CORS-Middleware nach dem Routing und vor den Endpunkten auf.Calls UseCors to add the CORS middleware after routing and before endpoints.
  • Gibt die Methode endpoints.MapGrpcService<GreeterService>() an, die CORS mit RequiresCors unterstützt.Specifies the endpoints.MapGrpcService<GreeterService>() method supports CORS with RequiresCors.

gRPC-Web und StreaminggRPC-Web and streaming

Herkömmliches gRPC über HTTP/2 unterstützt das Streamen in alle Richtungen.Traditional gRPC over HTTP/2 supports streaming in all directions. gRPC-Web bietet eingeschränkte Unterstützung für Streaming:gRPC-Web offers limited support for streaming:

  • gRPC-Web-Browserclients unterstützen das Aufrufen von Clientstreaming- und bidirektionalen Streamingmethoden nicht.gRPC-Web browser clients don't support calling client streaming and bidirectional streaming methods.
  • ASP.NET Core-gRPC-Dienste, die in Azure App Service und IIS gehostet werden, unterstützen das bidirektionale Streaming nicht.ASP.NET Core gRPC services hosted on Azure App Service and IIS don't support bidirectional streaming.

Bei der Verwendung von gRPC-Web wird nur der Einsatz von unären Methoden und Serverstreamingmethoden empfohlen.When using gRPC-Web, we only recommend the use of unary methods and server streaming methods.

Aufrufen von gRPC-Web über den BrowserCall gRPC-Web from the browser

Browser-Apps können gRPC-Web verwenden, um gRPC-Dienste aufzurufen.Browser apps can use gRPC-Web to call gRPC services. Es gibt einige Anforderungen und Einschränkungen beim Aufrufen von gRPC-Diensten mit gRPC-Web aus dem Browser heraus:There are some requirements and limitations when calling gRPC services with gRPC-Web from the browser:

  • Der Server muss für die Unterstützung von gRPC-Web konfiguriert worden sein.The server must have been configured to support gRPC-Web.
  • Clientstreaming und bidirektionale Streamingaufrufe werden nicht unterstützt.Client streaming and bidirectional streaming calls aren't supported. Das Serverstreaming wird unterstützt.Server streaming is supported.
  • Das Aufrufen von gRPC-Diensten in einer anderen Domäne erfordert die Konfiguration von CORS auf dem Server.Calling gRPC services on a different domain requires CORS to be configured on the server.

JavaScript gRPC-Web-ClientJavaScript gRPC-Web client

Es gibt einen JavaScript gRPC-Web-Client.There is a JavaScript gRPC-Web client. Anweisungen zur Verwendung von gRPC-Web aus JavaScript heraus finden Sie unter Schreiben von JavaScript-Clientcode mit gRPC-Web.For instructions on how to use gRPC-Web from JavaScript, see write JavaScript client code with gRPC-Web.

Konfigurieren von gRPC-Web mit dem .NET gRPC-ClientConfigure gRPC-Web with the .NET gRPC client

Der .NET gRPC-Client kann für gRPC-Web-Aufrufe konfiguriert werden.The .NET gRPC client can be configured to make gRPC-Web calls. Dies ist nützlich für Blazor WebAssembly-Apps, die im Browser gehostet werden und dieselben HTTP-Einschränkungen des JavaScript-Codes aufweisen.This is useful for Blazor WebAssembly apps, which are hosted in the browser and have the same HTTP limitations of JavaScript code. Das Aufrufen von gRPC-Web mit einem .NET-Client ist dasselbe wie das Aufrufen von HTTP/2 gRPC.Calling gRPC-Web with a .NET client is the same as HTTP/2 gRPC. Die einzige Änderung besteht darin, wie der Kanal erstellt wird.The only modification is how the channel is created.

So verwenden Sie gRPC-WebTo use gRPC-Web:

  • Fügen Sie einen Verweis auf das Paket Grpc.Net.Client.Web hinzu.Add a reference to the Grpc.Net.Client.Web package.
  • Stellen Sie sicher, dass der Verweis auf das Paket Grpc.Net.Client 2.29.0 oder höher ist.Ensure the reference to Grpc.Net.Client package is 2.29.0 or greater.
  • Konfigurieren Sie den Kanal für die Verwendung von GrpcWebHandler:Configure the channel to use the 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:The preceding code:

  • Konfiguriert einen Kanal zur Verwendung von gRPC-Web.Configures a channel to use gRPC-Web.
  • Erstellt einen Client und tätigt einen Aufruf über den Kanal.Creates a client and makes a call using the channel.

GrpcWebHandler hat die folgenden Konfigurationsoptionen:GrpcWebHandler has the following configuration options:

  • InnerHandler: Der zugrundeliegende HttpMessageHandler, der die gRPC HTTP-Anforderung stellt, z. B. HttpClientHandler.InnerHandler: The underlying HttpMessageHandler that makes the gRPC HTTP request, for example, HttpClientHandler.
  • GrpcWebMode: Ein Enumerationstyp, der angibt, ob die gRPC-HTTP-Anforderung Content-Type application/grpc-web oder application/grpc-web-text ist.GrpcWebMode: An enumeration type that specifies whether the gRPC HTTP request Content-Type is application/grpc-web or application/grpc-web-text.
    • GrpcWebMode.GrpcWeb konfiguriert Inhalte, die ohne Codierung gesendet werden.GrpcWebMode.GrpcWeb configures content to be sent without encoding. Standardwert.Default value.
    • GrpcWebMode.GrpcWebText konfiguriert den Inhalt so, dass er Base64-codiert ist.GrpcWebMode.GrpcWebText configures content to be base64 encoded. Erforderlich für Serverstreamingaufrufe in Browsern.Required for server streaming calls in browsers.
  • HttpVersion: Die Version des HTTP-Protokolls, die verwendet wird, um HttpRequestMessage.Version für die zugrunde liegende gRPC-HTTP-Anforderung festzulegen.HttpVersion: HTTP protocol Version used to set HttpRequestMessage.Version on the underlying gRPC HTTP request. gRPC-Web erfordert keine bestimmte Version und setzt die Standardeinstellung nicht außer Kraft, sofern nicht anders angegeben.gRPC-Web doesn't require a specific version and doesn't override the default unless specified.

Wichtig

Generierte gRPC-Clients verfügen über synchrone und asynchrone Methoden für den Aufruf unärer Methoden.Generated gRPC clients have sync and async methods for calling unary methods. Beispiel: SayHello ist synchron und SayHelloAsync ist asynchron.For example, SayHello is sync and SayHelloAsync is async. Der Aufruf einer synchronen Methode in einer Blazor WebAssembly-App führt dazu, dass die App nicht mehr reagiert.Calling a sync method in a Blazor WebAssembly app will cause the app to become unresponsive. Asynchrone Methoden müssen in Blazor WebAssembly immer verwendet werden.Async methods must always be used in Blazor WebAssembly.

Verwenden der gRPC-Clientfactory mit gRPC-WebUse gRPC client factory with gRPC-Web

Ein mit gRPC-Web kompatibler .NET-Client kann mithilfe der gRPC-Integration mit HttpClientFactory erstellt werden.A gRPC-Web compatible .NET client can be created using gRPC's integration with HttpClientFactory.

So verwenden Sie gRPC-Web mit der Clientfactory:To use gRPC-Web with client factory:

  • Fügen Sie der Projektdatei Paketverweise für folgende Pakete hinzu:Add package references to the project file for the following packages:
  • Registrieren Sie einen gRPC-Client mit Dependency Injection (DI), indem Sie die generische Erweiterungsmethode AddGrpcClient verwenden.Register a gRPC client with dependency injection (DI) using the generic AddGrpcClient extension method. In einer Blazor WebAssembly-App werden Dienste mit DI in Program.cs registriert.In a Blazor WebAssembly app, services are registered with DI in Program.cs.
  • Konfigurieren Sie GrpcWebHandler mithilfe der Erweiterungsmethode ConfigurePrimaryHttpMessageHandler.Configure GrpcWebHandler using the ConfigurePrimaryHttpMessageHandler extension method.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>((services, options) =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));

Weitere Informationen finden Sie unter gRPC-Integration von Clientfactory in .NET Core.For more information, see gRPC-Integration von Clientfactory in .NET Core.

Zusätzliche RessourcenAdditional resources