gRPC-Web nelle app ASP.NET Core gRPC

Di James Newton-King

Informazioni su come configurare un servizio gRPC core ASP.NET esistente per essere chiamabile dalle app del browser usando il protocollo gRPC-Web . gRPC-Web consente ai browser JavaScript e Blazor alle app di chiamare i servizi gRPC. Non è possibile chiamare un servizio HTTP/2 gRPC da un'app basata su browser. I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC.

Per istruzioni sull'aggiunta di un servizio gRPC a un'app ASP.NET Core esistente, vedere Aggiungere servizi gRPC a un'app ASP.NET Core.

Per istruzioni sulla creazione di un progetto gRPC, vedere Creare un client e un server gRPC di .NET Core in ASP.NET Core.

ASP.NET Core gRPC-Web e Envoy

Esistono due opzioni per aggiungere gRPC-Web a un'app ASP.NET Core:

  • Supportare gRPC-Web insieme a gRPC HTTP/2 in ASP.NET Core. Questa opzione usa il middleware fornito dal Grpc.AspNetCore.Web pacchetto.
  • Usare il supporto gRPC-Web del proxy Envoy per convertire gRPC-Web in gRPC HTTP/2. La chiamata tradotta viene quindi inoltrata all'app ASP.NET Core.

Esistono vantaggi e svantaggi per ogni approccio. Se l'ambiente di un'app usa già Envoy come proxy, potrebbe essere utile usare Envoy anche per fornire supporto gRPC-Web. Per una soluzione di base per gRPC-Web che richiede solo ASP.NET Core, Grpc.AspNetCore.Web è una buona scelta.

Configurare gRPC-Web in ASP.NET Core

I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC. gRPC-Web non richiede modifiche ai servizi. L'unica modifica consiste nell'impostare il middleware in Program.cs.

Per abilitare gRPC-Web con un servizio gRPC core ASP.NET:

  • Aggiungere un riferimento al Grpc.AspNetCore.Web pacchetto.
  • Configurare l'app per l'uso di gRPC-Web aggiungendo UseGrpcWeb e EnableGrpcWeb a Program.cs:
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();

Il codice precedente:

  • Aggiunge il middleware gRPC-Web, UseGrpcWeb, dopo il routing e prima degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta gRPC-Web con EnableGrpcWeb.

In alternativa, il middleware gRPC-Web può essere configurato in modo che tutti i servizi supportino gRPC-Web per impostazione predefinita e EnableGrpcWeb non siano necessari. Specificare new GrpcWebOptions { DefaultEnabled = true } quando viene aggiunto il middleware.

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

Nota

Si è verificato un problema noto che causa l'esito negativo di gRPC-Web quando è ospitato da HTTP.sys in .NET Core 3.x.

Una soluzione alternativa per usare gRPC-Web su HTTP.sys è disponibile in grpc-web sperimentale e UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web e CORS

La sicurezza del browser impedisce a una pagina Web di effettuare richieste a un dominio diverso da quello che ha distribuito la pagina Web. Questa restrizione si applica all'esecuzione di chiamate gRPC-Web con le app browser. Ad esempio, un'app browser servita da https://www.contoso.com viene bloccata dalla chiamata di servizi gRPC-Web ospitati in https://services.contoso.com. La condivisione di risorse tra le origini (CORS) può essere usata per ridurre questa restrizione.

Per consentire a un'app browser di effettuare chiamate gRPC-Web tra le origini, configurare CORS in ASP.NET Core. Usare il supporto CORS predefinito ed esporre intestazioni specifiche di gRPC con WithExposedHeaders.

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

Il codice precedente:

  • Chiama AddCors per aggiungere servizi CORS e configurare un criterio CORS che espone intestazioni specifiche di gRPC.
  • Chiama UseCors per aggiungere il middleware CORS dopo la configurazione del routing e prima della configurazione degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta CORS con RequireCors.

gRPC-Web e streaming

GRPC tradizionale su HTTP/2 supporta il client, il server e lo streaming bidirezionale. gRPC-Web offre supporto limitato per lo streaming:

  • I client gRPC-Web browser non supportano la chiamata di metodi di streaming client e di streaming bidirezionali.
  • I client .NET gRPC-Web non supportano la chiamata di metodi di streaming client e di streaming bidirezionali su HTTP/1.1.
  • ASP.NET servizi gRPC core ospitati nel servizio app Azure e IIS non supportano lo streaming bidirezionale.

Quando si usa gRPC-Web, è consigliabile usare solo metodi unari e metodi di streaming del server.

Protocollo HTTP

Il modello di servizio ASP.NET Core gRPC, incluso in .NET SDK, crea un'app configurata solo per HTTP/2. Si tratta di un'impostazione predefinita valida quando un'app supporta solo gRPC tradizionale su HTTP/2. gRPC-Web, tuttavia, funziona con HTTP/1.1 e HTTP/2. Alcune piattaforme, ad esempio UWP o Unity, non possono usare HTTP/2. Per supportare tutte le app client, configurare il server per abilitare HTTP/1.1 e HTTP/2.

Aggiornare il protocollo predefinito in appsettings.json:

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

In alternativa, configurare Kestrel gli endpoint nel codice di avvio.

L'abilitazione di HTTP/1.1 e HTTP/2 nella stessa porta richiede TLS per la negoziazione del protocollo. Per altre informazioni, vedere ASP.NET negoziazione del protocollo gRPC core.

Chiamare gRPC-Web dal browser

Le app browser possono usare gRPC-Web per chiamare i servizi gRPC. Esistono alcuni requisiti e limitazioni quando si chiamano i servizi gRPC con gRPC-Web dal browser:

  • Il server deve contenere la configurazione per supportare gRPC-Web.
  • Le chiamate di streaming client e di streaming bidirezionali non sono supportate. Lo streaming del server è supportato.
  • La chiamata di servizi gRPC in un dominio diverso richiede la configurazione CORS nel server.

Client JavaScript gRPC-Web

Esiste un client JavaScript gRPC-Web. Per istruzioni su come usare gRPC-Web da JavaScript, vedere Scrivere codice client JavaScript con gRPC-Web.

Configurare gRPC-Web con il client GRPC .NET

Il client GRPC .NET può essere configurato per effettuare chiamate gRPC-Web. Ciò è utile per Blazor WebAssembly le app, ospitate nel browser e hanno le stesse limitazioni HTTP del codice JavaScript. La chiamata a gRPC-Web con un client .NET è uguale a HTTP/2 gRPC. L'unica modifica è la modalità di creazione del canale.

Per usare gRPC-Web:

  • Aggiungere un riferimento al Grpc.Net.Client.Web pacchetto.
  • Verificare che il riferimento al Grpc.Net.Client pacchetto sia versione 2.29.0 o successiva.
  • Configurare il canale per l'uso di 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" });

Il codice precedente:

  • Configura un canale per l'uso di gRPC-Web.
  • Crea un client e effettua una chiamata usando il canale.

GrpcWebHandler include le opzioni di configurazione seguenti:

  • InnerHandler: sottostante HttpMessageHandler che effettua la richiesta HTTP gRPC, HttpClientHandlerad esempio .
  • GrpcWebMode: tipo di enumerazione che specifica se la richiesta Content-Type HTTP gRPC è application/grpc-web o application/grpc-web-text.
    • GrpcWebMode.GrpcWeb configura l'invio di contenuto senza codifica. Valore predefinito.
    • GrpcWebMode.GrpcWebText configura il contenuto con codifica Base64. Obbligatorio per le chiamate di streaming del server nei browser.
  • HttpVersion: protocollo Version HTTP usato per impostare HttpRequestMessage.Version sulla richiesta HTTP gRPC sottostante. gRPC-Web non richiede una versione specifica e non esegue l'override del valore predefinito, a meno che non sia specificato.

Importante

I client gRPC generati hanno metodi sincroni e asincroni per chiamare metodi unari. Ad esempio, SayHello è sincrono ed SayHelloAsync è asincrono. I metodi asincroni sono sempre necessari in Blazor WebAssembly. La chiamata a un metodo sincrono in un'app Blazor WebAssembly causa la mancata risposta dell'app.

Usare la factory client gRPC con gRPC-Web

Creare un client .NET compatibile con gRPC-Web usando la factory client gRPC:

  • Aggiungere riferimenti al pacchetto al file di progetto per i pacchetti seguenti:
  • Registrare un client gRPC con inserimento delle dipendenze usando il metodo di estensione generico AddGrpcClient . In un'app Blazor WebAssembly i servizi vengono registrati con l'inserimento delle dipendenze in Program.cs.
  • Configurare GrpcWebHandler usando il metodo di ConfigurePrimaryHttpMessageHandler estensione.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Per altre informazioni, vedere Integrazione della factory client gRPC in .NET.

Risorse aggiuntive

Informazioni su come configurare un servizio gRPC core ASP.NET esistente per essere chiamabile dalle app del browser usando il protocollo gRPC-Web . gRPC-Web consente ai browser JavaScript e Blazor alle app di chiamare i servizi gRPC. Non è possibile chiamare un servizio HTTP/2 gRPC da un'app basata su browser. I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC.

Per istruzioni sull'aggiunta di un servizio gRPC a un'app ASP.NET Core esistente, vedere Aggiungere servizi gRPC a un'app ASP.NET Core.

Per istruzioni sulla creazione di un progetto gRPC, vedere Creare un client e un server gRPC di .NET Core in ASP.NET Core.

ASP.NET Core gRPC-Web e Envoy

Esistono due opzioni per aggiungere gRPC-Web a un'app ASP.NET Core:

  • Supportare gRPC-Web insieme a gRPC HTTP/2 in ASP.NET Core. Questa opzione usa il middleware fornito dal Grpc.AspNetCore.Web pacchetto.
  • Usare il supporto gRPC-Web del proxy Envoy per convertire gRPC-Web in gRPC HTTP/2. La chiamata tradotta viene quindi inoltrata all'app ASP.NET Core.

Esistono vantaggi e svantaggi per ogni approccio. Se l'ambiente di un'app usa già Envoy come proxy, potrebbe essere utile usare Envoy anche per fornire supporto gRPC-Web. Per una soluzione di base per gRPC-Web che richiede solo ASP.NET Core, Grpc.AspNetCore.Web è una buona scelta.

Configurare gRPC-Web in ASP.NET Core

I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC. gRPC-Web non richiede modifiche ai servizi. L'unica modifica consiste nell'impostare il middelware in Program.cs.

Per abilitare gRPC-Web con un servizio gRPC core ASP.NET:

  • Aggiungere un riferimento al Grpc.AspNetCore.Web pacchetto.
  • Configurare l'app per l'uso di gRPC-Web aggiungendo UseGrpcWeb e EnableGrpcWeb a Program.cs:
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();

Il codice precedente:

  • Aggiunge il middleware gRPC-Web, UseGrpcWeb, dopo il routing e prima degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta gRPC-Web con EnableGrpcWeb.

In alternativa, il middleware gRPC-Web può essere configurato in modo che tutti i servizi supportino gRPC-Web per impostazione predefinita e EnableGrpcWeb non siano necessari. Specificare new GrpcWebOptions { DefaultEnabled = true } quando viene aggiunto il middleware.

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

Nota

Si è verificato un problema noto che causa l'esito negativo di gRPC-Web quando è ospitato da HTTP.sys in .NET Core 3.x.

Una soluzione alternativa per usare gRPC-Web su HTTP.sys è disponibile in grpc-web sperimentale e UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web e CORS

La sicurezza del browser impedisce a una pagina Web di effettuare richieste a un dominio diverso da quello che ha distribuito la pagina Web. Questa restrizione si applica all'esecuzione di chiamate gRPC-Web con le app browser. Ad esempio, un'app browser servita da https://www.contoso.com viene bloccata dalla chiamata di servizi gRPC-Web ospitati in https://services.contoso.com. La condivisione di risorse tra le origini (CORS) può essere usata per ridurre questa restrizione.

Per consentire a un'app browser di effettuare chiamate gRPC-Web tra le origini, configurare CORS in ASP.NET Core. Usare il supporto CORS predefinito ed esporre intestazioni specifiche di gRPC con WithExposedHeaders.

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

Il codice precedente:

  • Chiama AddCors per aggiungere servizi CORS e configurare un criterio CORS che espone intestazioni specifiche di gRPC.
  • Chiama UseCors per aggiungere il middleware CORS dopo la configurazione del routing e prima della configurazione degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta CORS con RequireCors.

gRPC-Web e streaming

GRPC tradizionale su HTTP/2 supporta il client, il server e lo streaming bidirezionale. gRPC-Web offre supporto limitato per lo streaming:

  • I client gRPC-Web browser non supportano la chiamata di metodi di streaming client e di streaming bidirezionali.
  • I client .NET gRPC-Web non supportano la chiamata di metodi di streaming client e di streaming bidirezionali su HTTP/1.1.
  • ASP.NET servizi gRPC core ospitati nel servizio app Azure e IIS non supportano lo streaming bidirezionale.

Quando si usa gRPC-Web, è consigliabile usare solo metodi unari e metodi di streaming del server.

Protocollo HTTP

Il modello di servizio ASP.NET Core gRPC, incluso in .NET SDK, crea un'app configurata solo per HTTP/2. Si tratta di un'impostazione predefinita valida quando un'app supporta solo gRPC tradizionale su HTTP/2. gRPC-Web, tuttavia, funziona con HTTP/1.1 e HTTP/2. Alcune piattaforme, ad esempio UWP o Unity, non possono usare HTTP/2. Per supportare tutte le app client, configurare il server per abilitare HTTP/1.1 e HTTP/2.

Aggiornare il protocollo predefinito in appsettings.json:

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

In alternativa, configurare Kestrel gli endpoint nel codice di avvio.

L'abilitazione di HTTP/1.1 e HTTP/2 nella stessa porta richiede TLS per la negoziazione del protocollo. Per altre informazioni, vedere ASP.NET negoziazione del protocollo gRPC core.

Chiamare gRPC-Web dal browser

Le app browser possono usare gRPC-Web per chiamare i servizi gRPC. Esistono alcuni requisiti e limitazioni quando si chiamano i servizi gRPC con gRPC-Web dal browser:

  • Il server deve contenere la configurazione per supportare gRPC-Web.
  • Le chiamate di streaming client e di streaming bidirezionali non sono supportate. Lo streaming del server è supportato.
  • La chiamata di servizi gRPC in un dominio diverso richiede la configurazione CORS nel server.

Client JavaScript gRPC-Web

Esiste un client JavaScript gRPC-Web. Per istruzioni su come usare gRPC-Web da JavaScript, vedere Scrivere codice client JavaScript con gRPC-Web.

Configurare gRPC-Web con il client GRPC .NET

Il client GRPC .NET può essere configurato per effettuare chiamate gRPC-Web. Ciò è utile per Blazor WebAssembly le app, ospitate nel browser e hanno le stesse limitazioni HTTP del codice JavaScript. La chiamata a gRPC-Web con un client .NET è uguale a HTTP/2 gRPC. L'unica modifica è la modalità di creazione del canale.

Per usare gRPC-Web:

  • Aggiungere un riferimento al Grpc.Net.Client.Web pacchetto.
  • Verificare che il riferimento al Grpc.Net.Client pacchetto sia versione 2.29.0 o successiva.
  • Configurare il canale per l'uso di 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" });

Il codice precedente:

  • Configura un canale per l'uso di gRPC-Web.
  • Crea un client e effettua una chiamata usando il canale.

GrpcWebHandler include le opzioni di configurazione seguenti:

  • InnerHandler: sottostante HttpMessageHandler che effettua la richiesta HTTP gRPC, HttpClientHandlerad esempio .
  • GrpcWebMode: tipo di enumerazione che specifica se la richiesta Content-Type HTTP gRPC è application/grpc-web o application/grpc-web-text.
    • GrpcWebMode.GrpcWeb configura l'invio di contenuto senza codifica. Valore predefinito.
    • GrpcWebMode.GrpcWebText configura il contenuto con codifica Base64. Obbligatorio per le chiamate di streaming del server nei browser.
  • HttpVersion: protocollo Version HTTP usato per impostare HttpRequestMessage.Version sulla richiesta HTTP gRPC sottostante. gRPC-Web non richiede una versione specifica e non esegue l'override del valore predefinito, a meno che non sia specificato.

Importante

I client gRPC generati hanno metodi sincroni e asincroni per chiamare metodi unari. Ad esempio, SayHello è sincrono ed SayHelloAsync è asincrono. I metodi asincroni sono sempre necessari in Blazor WebAssembly. La chiamata a un metodo sincrono in un'app Blazor WebAssembly causa la mancata risposta dell'app.

Usare la factory client gRPC con gRPC-Web

Creare un client .NET compatibile con gRPC-Web usando la factory client gRPC:

  • Aggiungere riferimenti al pacchetto al file di progetto per i pacchetti seguenti:
  • Registrare un client gRPC con inserimento delle dipendenze usando il metodo di estensione generico AddGrpcClient . In un'app Blazor WebAssembly i servizi vengono registrati con l'inserimento delle dipendenze in Program.cs.
  • Configurare GrpcWebHandler usando il metodo di ConfigurePrimaryHttpMessageHandler estensione.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Per altre informazioni, vedere Integrazione della factory client gRPC in .NET.

Risorse aggiuntive

Informazioni su come configurare un servizio gRPC core ASP.NET esistente per essere chiamabile dalle app del browser usando il protocollo gRPC-Web . gRPC-Web consente ai browser JavaScript e Blazor alle app di chiamare i servizi gRPC. Non è possibile chiamare un servizio HTTP/2 gRPC da un'app basata su browser. I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC.

Per istruzioni sull'aggiunta di un servizio gRPC a un'app ASP.NET Core esistente, vedere Aggiungere servizi gRPC a un'app ASP.NET Core.

Per istruzioni sulla creazione di un progetto gRPC, vedere Creare un client e un server gRPC di .NET Core in ASP.NET Core.

ASP.NET Core gRPC-Web e Envoy

Esistono due opzioni per aggiungere gRPC-Web a un'app ASP.NET Core:

  • Supportare gRPC-Web insieme a gRPC HTTP/2 in ASP.NET Core. Questa opzione usa il middleware fornito dal Grpc.AspNetCore.Web pacchetto.
  • Usare il supporto gRPC-Web del proxy Envoy per convertire gRPC-Web in gRPC HTTP/2. La chiamata tradotta viene quindi inoltrata all'app ASP.NET Core.

Esistono vantaggi e svantaggi per ogni approccio. Se l'ambiente di un'app usa già Envoy come proxy, potrebbe essere utile usare Envoy anche per fornire supporto gRPC-Web. Per una soluzione di base per gRPC-Web che richiede solo ASP.NET Core, Grpc.AspNetCore.Web è una buona scelta.

Configurare gRPC-Web in ASP.NET Core

I servizi gRPC ospitati in ASP.NET Core possono essere configurati per supportare gRPC-Web insieme a HTTP/2 gRPC. gRPC-Web non richiede modifiche ai servizi. L'unica modifica è la configurazione di avvio.

Per abilitare gRPC-Web con un servizio gRPC core ASP.NET:

  • Aggiungere un riferimento al Grpc.AspNetCore.Web pacchetto.
  • Configurare l'app per l'uso di gRPC-Web aggiungendo UseGrpcWeb e EnableGrpcWeb a 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();
    });
}

Il codice precedente:

  • Aggiunge il middleware gRPC-Web, UseGrpcWeb, dopo il routing e prima degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta gRPC-Web con EnableGrpcWeb.

In alternativa, il middleware gRPC-Web può essere configurato in modo che tutti i servizi supportino gRPC-Web per impostazione predefinita e EnableGrpcWeb non siano necessari. Specificare new GrpcWebOptions { DefaultEnabled = true } quando viene aggiunto il middleware.

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

Nota

Si è verificato un problema noto che causa l'esito negativo di gRPC-Web quando è ospitato da HTTP.sys in .NET Core 3.x.

Una soluzione alternativa per usare gRPC-Web su HTTP.sys è disponibile in grpc-web sperimentale e UseHttpSys()? (grpc/grpc-dotnet #853).

gRPC-Web e CORS

La sicurezza del browser impedisce a una pagina Web di effettuare richieste a un dominio diverso da quello che ha distribuito la pagina Web. Questa restrizione si applica all'esecuzione di chiamate gRPC-Web con le app browser. Ad esempio, un'app browser servita da https://www.contoso.com viene bloccata dalla chiamata di servizi gRPC-Web ospitati in https://services.contoso.com. La condivisione di risorse tra le origini (CORS) può essere usata per ridurre questa restrizione.

Per consentire a un'app browser di effettuare chiamate gRPC-Web tra le origini, configurare CORS in ASP.NET Core. Usare il supporto CORS predefinito ed esporre intestazioni specifiche di gRPC con 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");
    });
}

Il codice precedente:

  • Chiama AddCors per aggiungere servizi CORS e configurare un criterio CORS che espone intestazioni specifiche di gRPC.
  • Chiama UseCors per aggiungere il middleware CORS dopo la configurazione del routing e prima della configurazione degli endpoint.
  • Specifica che il endpoints.MapGrpcService<GreeterService>() metodo supporta CORS con RequireCors.

gRPC-Web e streaming

GRPC tradizionale su HTTP/2 supporta il client, il server e lo streaming bidirezionale. gRPC-Web offre supporto limitato per lo streaming:

  • I client gRPC-Web browser non supportano la chiamata di metodi di streaming client e di streaming bidirezionali.
  • I client .NET gRPC-Web non supportano la chiamata di metodi di streaming client e di streaming bidirezionali su HTTP/1.1.
  • ASP.NET servizi gRPC core ospitati nel servizio app Azure e IIS non supportano lo streaming bidirezionale.

Quando si usa gRPC-Web, è consigliabile usare solo metodi unari e metodi di streaming del server.

Protocollo HTTP

Il modello di servizio ASP.NET Core gRPC, incluso in .NET SDK, crea un'app configurata solo per HTTP/2. Si tratta di un'impostazione predefinita valida quando un'app supporta solo gRPC tradizionale su HTTP/2. gRPC-Web, tuttavia, funziona con HTTP/1.1 e HTTP/2. Alcune piattaforme, ad esempio UWP o Unity, non possono usare HTTP/2. Per supportare tutte le app client, configurare il server per abilitare HTTP/1.1 e HTTP/2.

Aggiornare il protocollo predefinito in appsettings.json:

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

In alternativa, configurare Kestrel gli endpoint nel codice di avvio.

L'abilitazione di HTTP/1.1 e HTTP/2 nella stessa porta richiede TLS per la negoziazione del protocollo. Per altre informazioni, vedere ASP.NET negoziazione del protocollo gRPC core.

Chiamare gRPC-Web dal browser

Le app browser possono usare gRPC-Web per chiamare i servizi gRPC. Esistono alcuni requisiti e limitazioni quando si chiamano i servizi gRPC con gRPC-Web dal browser:

  • Il server deve contenere la configurazione per supportare gRPC-Web.
  • Le chiamate di streaming client e di streaming bidirezionali non sono supportate. Lo streaming del server è supportato.
  • La chiamata di servizi gRPC in un dominio diverso richiede la configurazione CORS nel server.

Client JavaScript gRPC-Web

Esiste un client JavaScript gRPC-Web. Per istruzioni su come usare gRPC-Web da JavaScript, vedere Scrivere codice client JavaScript con gRPC-Web.

Configurare gRPC-Web con il client GRPC .NET

Il client GRPC .NET può essere configurato per effettuare chiamate gRPC-Web. Ciò è utile per Blazor WebAssembly le app, ospitate nel browser e hanno le stesse limitazioni HTTP del codice JavaScript. La chiamata a gRPC-Web con un client .NET è uguale a HTTP/2 gRPC. L'unica modifica è la modalità di creazione del canale.

Per usare gRPC-Web:

  • Aggiungere un riferimento al Grpc.Net.Client.Web pacchetto.
  • Verificare che il riferimento al Grpc.Net.Client pacchetto sia versione 2.29.0 o successiva.
  • Configurare il canale per l'uso di 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" });

Il codice precedente:

  • Configura un canale per l'uso di gRPC-Web.
  • Crea un client e effettua una chiamata usando il canale.

GrpcWebHandler include le opzioni di configurazione seguenti:

  • InnerHandler: sottostante HttpMessageHandler che effettua la richiesta HTTP gRPC, HttpClientHandlerad esempio .
  • GrpcWebMode: tipo di enumerazione che specifica se la richiesta Content-Type HTTP gRPC è application/grpc-web o application/grpc-web-text.
    • GrpcWebMode.GrpcWeb configura l'invio di contenuto senza codifica. Valore predefinito.
    • GrpcWebMode.GrpcWebText configura il contenuto con codifica Base64. Obbligatorio per le chiamate di streaming del server nei browser.
  • HttpVersion: protocollo Version HTTP usato per impostare HttpRequestMessage.Version sulla richiesta HTTP gRPC sottostante. gRPC-Web non richiede una versione specifica e non esegue l'override del valore predefinito, a meno che non sia specificato.

Importante

I client gRPC generati hanno metodi sincroni e asincroni per chiamare metodi unari. Ad esempio, SayHello è sincrono ed SayHelloAsync è asincrono. I metodi asincroni sono sempre necessari in Blazor WebAssembly. La chiamata a un metodo sincrono in un'app Blazor WebAssembly causa la mancata risposta dell'app.

Usare la factory client gRPC con gRPC-Web

Creare un client .NET compatibile con gRPC-Web usando la factory client gRPC:

  • Aggiungere riferimenti al pacchetto al file di progetto per i pacchetti seguenti:
  • Registrare un client gRPC con inserimento delle dipendenze usando il metodo di estensione generico AddGrpcClient . In un'app Blazor WebAssembly i servizi vengono registrati con l'inserimento delle dipendenze in Program.cs.
  • Configurare GrpcWebHandler usando il metodo di ConfigurePrimaryHttpMessageHandler estensione.
builder.Services
    .AddGrpcClient<Greet.GreeterClient>(options =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(new HttpClientHandler()));

Per altre informazioni, vedere Integrazione della factory client gRPC in .NET.

Risorse aggiuntive