8.8 KiB
title | author | description | monikerRange | ms.author | ms.date | no-loc | uid | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Use gRPC in browser apps | jamesnk | Learn how to configure gRPC services on ASP.NET Core to be callable from browser apps using gRPC-Web. | >= aspnetcore-3.0 | jamesnk | 06/30/2020 |
|
grpc/browser |
Use gRPC in browser apps
Learn how to configure an existing ASP.NET Core gRPC service to be callable from browser apps, using the gRPC-Web protocol. gRPC-Web allows browser JavaScript and Blazor apps to call gRPC services. It's not possible to call an HTTP/2 gRPC service from a browser-based app. gRPC services hosted in ASP.NET Core can be configured to support gRPC-Web alongside HTTP/2 gRPC.
For instructions on adding a gRPC service to an existing ASP.NET Core app, see Add gRPC services to an ASP.NET Core app.
For instructions on creating a gRPC project, see xref:tutorials/grpc/grpc-start.
gRPC-Web in ASP.NET Core vs. Envoy
There are two choices for how to add gRPC-Web to an ASP.NET Core app:
- Support gRPC-Web alongside gRPC HTTP/2 in ASP.NET Core. This option uses middleware provided by the
Grpc.AspNetCore.Web
package. - Use the Envoy proxy's gRPC-Web support to translate gRPC-Web to gRPC HTTP/2. The translated call is then forwarded onto the ASP.NET Core app.
There are pros and cons to each approach. 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. For a basic solution for gRPC-Web that only requires ASP.NET Core, Grpc.AspNetCore.Web
is a good choice.
Configure gRPC-Web in ASP.NET Core
gRPC services hosted in ASP.NET Core can be configured to support gRPC-Web alongside HTTP/2 gRPC. gRPC-Web does not require any changes to services. The only modification is startup configuration.
To enable gRPC-Web with an ASP.NET Core gRPC service:
- Add a reference to the Grpc.AspNetCore.Web package.
- Configure the app to use gRPC-Web by adding
UseGrpcWeb
andEnableGrpcWeb
to Startup.cs:
The preceding code:
- Adds the gRPC-Web middleware,
UseGrpcWeb
, after routing and before endpoints. - Specifies the
endpoints.MapGrpcService<GreeterService>()
method supports gRPC-Web withEnableGrpcWeb
.
Alternatively, the gRPC-Web middleware can be configured so all services support gRPC-Web by default and EnableGrpcWeb
isn't required. Specify new GrpcWebOptions { DefaultEnabled = true }
when the middleware is added.
[!NOTE] There is a known issue that causes gRPC-Web to fail when hosted by Http.sys in .NET Core 3.x.
A workaround to get gRPC-Web working on Http.sys is available here.
gRPC-Web and CORS
Browser security prevents a web page from making requests to a different domain than the one that served the web page. This restriction applies to making gRPC-Web calls with browser apps. For example, a browser app served by https://www.contoso.com
is blocked from calling gRPC-Web services hosted on https://services.contoso.com
. Cross Origin Resource Sharing (CORS) can be used to relax this restriction.
To allow a browser app to make cross-origin gRPC-Web calls, set up CORS in ASP.NET Core. Use the built-in CORS support, and expose gRPC-specific headers with xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.WithExposedHeaders%2A.
The preceding code:
- Calls
AddCors
to add CORS services and configures a CORS policy that exposes gRPC-specific headers. - Calls
UseCors
to add the CORS middleware after routing and before endpoints. - Specifies the
endpoints.MapGrpcService<GreeterService>()
method supports CORS withRequiresCors
.
gRPC-Web and streaming
Traditional gRPC over HTTP/2 supports streaming in all directions. gRPC-Web offers limited support for streaming:
- gRPC-Web browser clients don't support calling client streaming and bidirectional streaming methods.
- ASP.NET Core gRPC services hosted on Azure App Service and IIS don't support bidirectional streaming.
When using gRPC-Web, we only recommend the use of unary methods and server streaming methods.
Call gRPC-Web from the browser
Browser apps can use gRPC-Web to call gRPC services. There are some requirements and limitations when calling gRPC services with gRPC-Web from the browser:
- The server must have been configured to support gRPC-Web.
- Client streaming and bidirectional streaming calls aren't supported. Server streaming is supported.
- Calling gRPC services on a different domain requires CORS to be configured on the server.
JavaScript gRPC-Web client
There is a JavaScript gRPC-Web client. For instructions on how to use gRPC-Web from JavaScript, see write JavaScript client code with gRPC-Web.
Configure gRPC-Web with the .NET gRPC client
The .NET gRPC client can be configured to make gRPC-Web calls. This is useful for Blazor WebAssembly apps, which are hosted in the browser and have the same HTTP limitations of JavaScript code. Calling gRPC-Web with a .NET client is the same as HTTP/2 gRPC. The only modification is how the channel is created.
To use gRPC-Web:
- Add a reference to the Grpc.Net.Client.Web package.
- Ensure the reference to Grpc.Net.Client package is 2.29.0 or greater.
- Configure the channel to use the
GrpcWebHandler
:
The preceding code:
- Configures a channel to use gRPC-Web.
- Creates a client and makes a call using the channel.
GrpcWebHandler
has the following configuration options:
- InnerHandler: The underlying xref:System.Net.Http.HttpMessageHandler that makes the gRPC HTTP request, for example,
HttpClientHandler
. - GrpcWebMode: An enumeration type that specifies whether the gRPC HTTP request
Content-Type
isapplication/grpc-web
orapplication/grpc-web-text
.GrpcWebMode.GrpcWeb
configures content to be sent without encoding. Default value.GrpcWebMode.GrpcWebText
configures content to be base64 encoded. Required for server streaming calls in browsers.
- HttpVersion: HTTP protocol
Version
used to set HttpRequestMessage.Version on the underlying gRPC HTTP request. gRPC-Web doesn't require a specific version and doesn't override the default unless specified.
[!IMPORTANT] Generated gRPC clients have sync and async methods for calling unary methods. For example,
SayHello
is sync andSayHelloAsync
is async. Calling a sync method in a Blazor WebAssembly app will cause the app to become unresponsive. Async methods must always be used in Blazor WebAssembly.
Use gRPC client factory with gRPC-Web
A gRPC-Web compatible .NET client can be created using gRPC's integration with HttpClientFactory.
To use gRPC-Web with client factory:
- Add package references to the project file for the following packages:
- Register a gRPC client with dependency injection (DI) using the generic
AddGrpcClient
extension method. In a Blazor WebAssembly app, services are registered with DI inProgram.cs
. - Configure
GrpcWebHandler
using the xref:Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler%2A extension method.
builder.Services
.AddGrpcClient<Greet.GreeterClient>((services, options) =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));
For more information, see xref:grpc/clientfactory.