ASP.NET Core gRPC 應用程式中的 gRPC-Web
注意
這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
了解如何使用 gRPC-Web 通訊協定,將現有的 ASP.NET Core gRPC 服務設定為可從瀏覽器應用程式呼叫。 gRPC-Web 允許瀏覽器 JavaScript 和 Blazor 應用程式呼叫 gRPC 服務。 您無法從瀏覽器型應用程式呼叫 HTTP/2 gRPC 服務。 裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。
如需將 gRPC 服務新增至現有 ASP.NET Core 應用程式的指示,請參閱將 gRPC 服務新增至 ASP.NET Core 應用程式。
如需建立 gRPC 專案的指示,請參閱在 ASP.NET Core 中建立 .NET Core gRPC 用戶端和伺服器。
ASP.NET Core gRPC-Web 與 Envoy
有兩個選項可用來將 gRPC-Web 新增至 ASP.NET Core 應用程式:
- 在 ASP.NET Core 中支援 gRPC-Web 與 gRPC HTTP/2。 此選項使用
Grpc.AspNetCore.Web
套件所提供的中介軟體。 - 使用 Envoy Proxy 的 gRPC-Web 支援,將 gRPC-Web 轉譯為 gRPC HTTP/2。 轉譯的呼叫接著會轉接至 ASP.NET Core 應用程式。
每個方法都有優缺點。 如果應用程式的環境已經使用 Envoy 作為 Proxy,則使用 Envoy 提供 gRPC-Web 支援可能很合理。 對於只需要 ASP.NET Core 的 gRPC-Web 基本解決方案,Grpc.AspNetCore.Web
是不錯的選擇。
在 ASP.NET Core 中設定 gRPC-Web
裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。 gRPC-Web 不需要對服務進行任何變更。 唯一的修改是在 Program.cs
設定中介軟體。
若要使用 ASP.NET Core gRPC 服務啟用 gRPC-Web:
- 將參考新增至
Grpc.AspNetCore.Web
套件。 - 將
UseGrpcWeb
和EnableGrpcWeb
新增至Program.cs
,將應用程式設定為使用 gRPC-Web:
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 using the gRPC-Web protocol");
app.Run();
上述 程式碼:
- 在路由之後,以及在端點之前新增 gRPC-Web 中介軟體
UseGrpcWeb
。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用EnableGrpcWeb
支援 gRPC-Web。
或者,您可以設定 gRPC-Web 中介軟體,讓所有服務預設都支援 gRPC-Web,而且不需要 EnableGrpcWeb
。 新增中介軟體時指定 new GrpcWebOptions { DefaultEnabled = true }
。
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 using the gRPC-Web protocol");
app.Run();
注意
已知問題會導致 gRPC-Web 在 .NET Core 3.x 中由 HTTP.sys 裝載時失敗。
Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853) 中提供可讓 gRPC-Web 在 HTTP.sys 上使用的因應措施。
gRPC-Web 和 CORS
瀏覽器安全性可防止網頁向提供網頁的不同網域提出要求。 這項限制適用於使用瀏覽器應用程式進行 gRPC-Web 呼叫。 例如,https://www.contoso.com
所提供服務的瀏覽器應用程式會遭到封鎖,而無法呼叫裝載在 https://services.contoso.com
上的 gRPC-Web 服務。 跨原始來源資源分享 (CORS) 可用來放寬這項限制。
若要允許瀏覽器應用程式進行跨原始來源 gRPC-Web 呼叫,請在 ASP.NET Core 中設定 CORS。 使用內建 CORS 支援,並使用 WithExposedHeaders 公開 gRPC 特定標頭。
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 using the gRPC-Web protocol");
app.Run();
上述 程式碼:
- 呼叫
AddCors
以新增 CORS 服務,並設定公開 gRPC 特定標頭的 CORS 原則。 - 在路由設定之後和端點設定之前,呼叫
UseCors
以新增 CORS 中介軟體。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用RequireCors
支援 CORS。
gRPC-Web 和串流
透過 HTTP/2 的傳統 gRPC 支援用戶端、伺服器和雙向串流。 gRPC-Web 提供有限的串流支援:
- gRPC-Web 瀏覽器用戶端不支援呼叫用戶端串流和雙向串流方法。
- gRPC-Web .NET 用戶端不支援透過 HTTP/1.1 呼叫用戶端串流和雙向串流方法。
- Azure App Service 和 IIS 上裝載的 ASP.NET Core gRPC 服務不支援雙向串流。
使用 gRPC-Web 時,我們只建議使用一元方法和伺服器串流方法。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本會建立只針對 HTTP/2 設定的應用程式。 當應用程式只支援透過 HTTP/2 的傳統 gRPC 時,這是很好的預設值。 不過,gRPC-Web 同時適用於 HTTP/1.1 和 HTTP/2。 某些平台,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 appsettings.json
中的預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
在相同的連接埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需詳細資訊,請參閱 ASP.NET Core gRPC 通訊協定交涉。
從瀏覽器呼叫 gRPC-Web
瀏覽器應用程式可以使用 gRPC-Web 來呼叫 gRPC 服務。 從瀏覽器使用 gRPC-Web 呼叫 gRPC 服務時,有一些需求和限制:
- 伺服器必須包含支援 gRPC-Web 的組態設定。
- 不支援用戶端串流和雙向串流呼叫。 支援伺服器串流。
- 在不同的網域上呼叫 gRPC 服務需要伺服器上的 CORS 設定。
JavaScript gRPC-Web 用戶端
存在 JavaScript gRPC-Web 用戶端。 如需如何從 JavaScript 使用 gRPC-Web 的指示,請參閱使用 gRPC-Web 撰寫 JavaScript 用戶端程式碼。
使用 .NET gRPC 用戶端設定 gRPC-Web
.NET gRPC 用戶端可以設定為進行 gRPC-Web 呼叫。 這對於裝載於瀏覽器中且 JavaScript 程式碼具有相同 HTTP 限制的 Blazor WebAssembly 應用程式很有用。 使用 .NET 用戶端呼叫 gRPC-Web 與 HTTP/2 gRPC 相同。 唯一的修改是通道的建立方式。
若要使用 gRPC-Web:
- 將參考新增至
Grpc.Net.Client.Web
套件。 - 請確定
Grpc.Net.Client
套件的參考是 2.29.0 版或更新版本。 - 將通道設定為使用
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" });
上述 程式碼:
- 設定通道以使用 gRPC-Web。
- 建立用戶端,並使用通道進行呼叫。
GrpcWebHandler
具有下列組態選項:
InnerHandler
:發出 gRPC HTTP 要求的基礎 HttpMessageHandler,例如HttpClientHandler
。GrpcWebMode
:列舉型別,指定 gRPC HTTP 要求Content-Type
為application/grpc-web
或application/grpc-web-text
。GrpcWebMode.GrpcWeb
會設定傳送內容而不使用編碼。 預設值。GrpcWebMode.GrpcWebText
會設定 base64 編碼的內容。 在瀏覽器中的伺服器串流呼叫是必要的。
HttpVersion
:用來在基礎 gRPC HTTP 要求上設定 HttpRequestMessage.Version 的 HTTP 通訊協定Version
。 gRPC-Web 不需要特定版本,而且除非指定,否則不會覆寫預設值。
重要
產生的 gRPC 用戶端具有同步和非同步方法來呼叫一元方法。 例如,SayHello
是同步,而 SayHelloAsync
是非同步。 在 Blazor WebAssembly 中一律需要非同步方法。 在 Blazor WebAssembly 應用程式中呼叫同步方法會導致應用程式變得沒有回應。
搭配 gRPC-Web 使用 gRPC 用戶端 Factory
使用 gRPC 用戶端 Factory 建立與 gRPC-Web 相容的 .NET 用戶端:
- 將套件參考新增至下列套件的專案檔:
- 使用泛型
AddGrpcClient
擴充方法向相依性插入 (DI) 註冊 gRPC 用戶端。 在應用程式 Blazor WebAssembly 中,服務會在Program.cs
中向 DI 註冊。 - 使用 ConfigurePrimaryHttpMessageHandler 擴充方法設定
GrpcWebHandler
。
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
如需詳細資訊,請參閱 .NET 中的 gRPC 用戶端 Factory 整合。
其他資源
了解如何使用 gRPC-Web 通訊協定,將現有的 ASP.NET Core gRPC 服務設定為可從瀏覽器應用程式呼叫。 gRPC-Web 允許瀏覽器 JavaScript 和 Blazor 應用程式呼叫 gRPC 服務。 您無法從瀏覽器型應用程式呼叫 HTTP/2 gRPC 服務。 裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。
如需將 gRPC 服務新增至現有 ASP.NET Core 應用程式的指示,請參閱將 gRPC 服務新增至 ASP.NET Core 應用程式。
如需建立 gRPC 專案的指示,請參閱在 ASP.NET Core 中建立 .NET Core gRPC 用戶端和伺服器。
ASP.NET Core gRPC-Web 與 Envoy
有兩個選項可用來將 gRPC-Web 新增至 ASP.NET Core 應用程式:
- 在 ASP.NET Core 中支援 gRPC-Web 與 gRPC HTTP/2。 此選項使用
Grpc.AspNetCore.Web
套件所提供的中介軟體。 - 使用 Envoy Proxy 的 gRPC-Web 支援,將 gRPC-Web 轉譯為 gRPC HTTP/2。 轉譯的呼叫接著會轉接至 ASP.NET Core 應用程式。
每個方法都有優缺點。 如果應用程式的環境已經使用 Envoy 作為 Proxy,則使用 Envoy 提供 gRPC-Web 支援可能很合理。 對於只需要 ASP.NET Core 的 gRPC-Web 基本解決方案,Grpc.AspNetCore.Web
是不錯的選擇。
在 ASP.NET Core 中設定 gRPC-Web
裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。 gRPC-Web 不需要對服務進行任何變更。 唯一的修改是在 Program.cs
設定 middelware。
若要使用 ASP.NET Core gRPC 服務啟用 gRPC-Web:
- 將參考新增至
Grpc.AspNetCore.Web
套件。 - 將
UseGrpcWeb
和EnableGrpcWeb
新增至Program.cs
,將應用程式設定為使用 gRPC-Web:
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 using the gRPC-Web protocol");
app.Run();
上述 程式碼:
- 在路由之後,以及在端點之前新增 gRPC-Web 中介軟體
UseGrpcWeb
。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用EnableGrpcWeb
支援 gRPC-Web。
或者,您可以設定 gRPC-Web 中介軟體,讓所有服務預設都支援 gRPC-Web,而且不需要 EnableGrpcWeb
。 新增中介軟體時指定 new GrpcWebOptions { DefaultEnabled = true }
。
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 using the gRPC-Web protocol");
app.Run();
注意
已知問題會導致 gRPC-Web 在 .NET Core 3.x 中由 HTTP.sys 裝載時失敗。
Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853) 中提供可讓 gRPC-Web 在 HTTP.sys 上使用的因應措施。
gRPC-Web 和 CORS
瀏覽器安全性可防止網頁向提供網頁的不同網域提出要求。 這項限制適用於使用瀏覽器應用程式進行 gRPC-Web 呼叫。 例如,https://www.contoso.com
所提供服務的瀏覽器應用程式會遭到封鎖,而無法呼叫裝載在 https://services.contoso.com
上的 gRPC-Web 服務。 跨原始來源資源分享 (CORS) 可用來放寬這項限制。
若要允許瀏覽器應用程式進行跨原始來源 gRPC-Web 呼叫,請在 ASP.NET Core 中設定 CORS。 使用內建 CORS 支援,並使用 WithExposedHeaders 公開 gRPC 特定標頭。
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 using the gRPC-Web protocol");
app.Run();
上述 程式碼:
- 呼叫
AddCors
以新增 CORS 服務,並設定公開 gRPC 特定標頭的 CORS 原則。 - 在路由設定之後和端點設定之前,呼叫
UseCors
以新增 CORS 中介軟體。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用RequireCors
支援 CORS。
gRPC-Web 和串流
透過 HTTP/2 的傳統 gRPC 支援用戶端、伺服器和雙向串流。 gRPC-Web 提供有限的串流支援:
- gRPC-Web 瀏覽器用戶端不支援呼叫用戶端串流和雙向串流方法。
- gRPC-Web .NET 用戶端不支援透過 HTTP/1.1 呼叫用戶端串流和雙向串流方法。
- Azure App Service 和 IIS 上裝載的 ASP.NET Core gRPC 服務不支援雙向串流。
使用 gRPC-Web 時,我們只建議使用一元方法和伺服器串流方法。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本會建立只針對 HTTP/2 設定的應用程式。 當應用程式只支援透過 HTTP/2 的傳統 gRPC 時,這是很好的預設值。 不過,gRPC-Web 同時適用於 HTTP/1.1 和 HTTP/2。 某些平台,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 appsettings.json
中的預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
在相同的連接埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需詳細資訊,請參閱 ASP.NET Core gRPC 通訊協定交涉。
從瀏覽器呼叫 gRPC-Web
瀏覽器應用程式可以使用 gRPC-Web 來呼叫 gRPC 服務。 從瀏覽器使用 gRPC-Web 呼叫 gRPC 服務時,有一些需求和限制:
- 伺服器必須包含支援 gRPC-Web 的組態設定。
- 不支援用戶端串流和雙向串流呼叫。 支援伺服器串流。
- 在不同的網域上呼叫 gRPC 服務需要伺服器上的 CORS 設定。
JavaScript gRPC-Web 用戶端
存在 JavaScript gRPC-Web 用戶端。 如需如何從 JavaScript 使用 gRPC-Web 的指示,請參閱使用 gRPC-Web 撰寫 JavaScript 用戶端程式碼。
使用 .NET gRPC 用戶端設定 gRPC-Web
.NET gRPC 用戶端可以設定為進行 gRPC-Web 呼叫。 這對於裝載於瀏覽器中且 JavaScript 程式碼具有相同 HTTP 限制的 Blazor WebAssembly 應用程式很有用。 使用 .NET 用戶端呼叫 gRPC-Web 與 HTTP/2 gRPC 相同。 唯一的修改是通道的建立方式。
若要使用 gRPC-Web:
- 將參考新增至
Grpc.Net.Client.Web
套件。 - 請確定
Grpc.Net.Client
套件的參考是 2.29.0 版或更新版本。 - 將通道設定為使用
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" });
上述 程式碼:
- 設定通道以使用 gRPC-Web。
- 建立用戶端,並使用通道進行呼叫。
GrpcWebHandler
具有下列組態選項:
InnerHandler
:發出 gRPC HTTP 要求的基礎 HttpMessageHandler,例如HttpClientHandler
。GrpcWebMode
:列舉型別,指定 gRPC HTTP 要求Content-Type
為application/grpc-web
或application/grpc-web-text
。GrpcWebMode.GrpcWeb
會設定傳送內容而不使用編碼。 預設值。GrpcWebMode.GrpcWebText
會設定 base64 編碼的內容。 在瀏覽器中的伺服器串流呼叫是必要的。
HttpVersion
:用來在基礎 gRPC HTTP 要求上設定 HttpRequestMessage.Version 的 HTTP 通訊協定Version
。 gRPC-Web 不需要特定版本,而且除非指定,否則不會覆寫預設值。
重要
產生的 gRPC 用戶端具有同步和非同步方法來呼叫一元方法。 例如,SayHello
是同步,而 SayHelloAsync
是非同步。 在 Blazor WebAssembly 中一律需要非同步方法。 在 Blazor WebAssembly 應用程式中呼叫同步方法會導致應用程式變得沒有回應。
搭配 gRPC-Web 使用 gRPC 用戶端 Factory
使用 gRPC 用戶端 Factory 建立與 gRPC-Web 相容的 .NET 用戶端:
- 將套件參考新增至下列套件的專案檔:
- 使用泛型
AddGrpcClient
擴充方法向相依性插入 (DI) 註冊 gRPC 用戶端。 在應用程式 Blazor WebAssembly 中,服務會在Program.cs
中向 DI 註冊。 - 使用 ConfigurePrimaryHttpMessageHandler 擴充方法設定
GrpcWebHandler
。
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
如需詳細資訊,請參閱 .NET 中的 gRPC 用戶端 Factory 整合。
其他資源
了解如何使用 gRPC-Web 通訊協定,將現有的 ASP.NET Core gRPC 服務設定為可從瀏覽器應用程式呼叫。 gRPC-Web 允許瀏覽器 JavaScript 和 Blazor 應用程式呼叫 gRPC 服務。 您無法從瀏覽器型應用程式呼叫 HTTP/2 gRPC 服務。 裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。
如需將 gRPC 服務新增至現有 ASP.NET Core 應用程式的指示,請參閱將 gRPC 服務新增至 ASP.NET Core 應用程式。
如需建立 gRPC 專案的指示,請參閱在 ASP.NET Core 中建立 .NET Core gRPC 用戶端和伺服器。
ASP.NET Core gRPC-Web 與 Envoy
有兩個選項可用來將 gRPC-Web 新增至 ASP.NET Core 應用程式:
- 在 ASP.NET Core 中支援 gRPC-Web 與 gRPC HTTP/2。 此選項使用
Grpc.AspNetCore.Web
套件所提供的中介軟體。 - 使用 Envoy Proxy 的 gRPC-Web 支援,將 gRPC-Web 轉譯為 gRPC HTTP/2。 轉譯的呼叫接著會轉接至 ASP.NET Core 應用程式。
每個方法都有優缺點。 如果應用程式的環境已經使用 Envoy 作為 Proxy,則使用 Envoy 提供 gRPC-Web 支援可能很合理。 對於只需要 ASP.NET Core 的 gRPC-Web 基本解決方案,Grpc.AspNetCore.Web
是不錯的選擇。
在 ASP.NET Core 中設定 gRPC-Web
裝載於 ASP.NET Core 中的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。 gRPC-Web 不需要對服務進行任何變更。 唯一的修改是啟動組態。
若要使用 ASP.NET Core gRPC 服務啟用 gRPC-Web:
- 將參考新增至
Grpc.AspNetCore.Web
套件。 - 將
UseGrpcWeb
和EnableGrpcWeb
新增至Startup.cs
,將應用程式設定為使用 gRPC-Web:
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();
});
}
上述 程式碼:
- 在路由之後,以及在端點之前新增 gRPC-Web 中介軟體
UseGrpcWeb
。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用EnableGrpcWeb
支援 gRPC-Web。
或者,您可以設定 gRPC-Web 中介軟體,讓所有服務預設都支援 gRPC-Web,而且不需要 EnableGrpcWeb
。 新增中介軟體時指定 new GrpcWebOptions { DefaultEnabled = true }
。
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>();
});
}
}
注意
已知問題會導致 gRPC-Web 在 .NET Core 3.x 中由 HTTP.sys 裝載時失敗。
Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853) 中提供可讓 gRPC-Web 在 HTTP.sys 上使用的因應措施。
gRPC-Web 和 CORS
瀏覽器安全性可防止網頁向提供網頁的不同網域提出要求。 這項限制適用於使用瀏覽器應用程式進行 gRPC-Web 呼叫。 例如,https://www.contoso.com
所提供服務的瀏覽器應用程式會遭到封鎖,而無法呼叫裝載在 https://services.contoso.com
上的 gRPC-Web 服務。 跨原始來源資源分享 (CORS) 可用來放寬這項限制。
若要允許瀏覽器應用程式進行跨原始來源 gRPC-Web 呼叫,請在 ASP.NET Core 中設定 CORS。 使用內建 CORS 支援,並使用 WithExposedHeaders 公開 gRPC 特定標頭。
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");
});
}
上述 程式碼:
- 呼叫
AddCors
以新增 CORS 服務,並設定公開 gRPC 特定標頭的 CORS 原則。 - 在路由設定之後和端點設定之前,呼叫
UseCors
以新增 CORS 中介軟體。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法使用RequireCors
支援 CORS。
gRPC-Web 和串流
透過 HTTP/2 的傳統 gRPC 支援用戶端、伺服器和雙向串流。 gRPC-Web 提供有限的串流支援:
- gRPC-Web 瀏覽器用戶端不支援呼叫用戶端串流和雙向串流方法。
- gRPC-Web .NET 用戶端不支援透過 HTTP/1.1 呼叫用戶端串流和雙向串流方法。
- Azure App Service 和 IIS 上裝載的 ASP.NET Core gRPC 服務不支援雙向串流。
使用 gRPC-Web 時,我們只建議使用一元方法和伺服器串流方法。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本會建立只針對 HTTP/2 設定的應用程式。 當應用程式只支援透過 HTTP/2 的傳統 gRPC 時,這是很好的預設值。 不過,gRPC-Web 同時適用於 HTTP/1.1 和 HTTP/2。 某些平台,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 appsettings.json
中的預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
在相同的連接埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需詳細資訊,請參閱 ASP.NET Core gRPC 通訊協定交涉。
從瀏覽器呼叫 gRPC-Web
瀏覽器應用程式可以使用 gRPC-Web 來呼叫 gRPC 服務。 從瀏覽器使用 gRPC-Web 呼叫 gRPC 服務時,有一些需求和限制:
- 伺服器必須包含支援 gRPC-Web 的組態設定。
- 不支援用戶端串流和雙向串流呼叫。 支援伺服器串流。
- 在不同的網域上呼叫 gRPC 服務需要伺服器上的 CORS 設定。
JavaScript gRPC-Web 用戶端
存在 JavaScript gRPC-Web 用戶端。 如需如何從 JavaScript 使用 gRPC-Web 的指示,請參閱使用 gRPC-Web 撰寫 JavaScript 用戶端程式碼。
使用 .NET gRPC 用戶端設定 gRPC-Web
.NET gRPC 用戶端可以設定為進行 gRPC-Web 呼叫。 這對於裝載於瀏覽器中且 JavaScript 程式碼具有相同 HTTP 限制的 Blazor WebAssembly 應用程式很有用。 使用 .NET 用戶端呼叫 gRPC-Web 與 HTTP/2 gRPC 相同。 唯一的修改是通道的建立方式。
若要使用 gRPC-Web:
- 將參考新增至
Grpc.Net.Client.Web
套件。 - 請確定
Grpc.Net.Client
套件的參考是 2.29.0 版或更新版本。 - 將通道設定為使用
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" });
上述 程式碼:
- 設定通道以使用 gRPC-Web。
- 建立用戶端,並使用通道進行呼叫。
GrpcWebHandler
具有下列組態選項:
InnerHandler
:發出 gRPC HTTP 要求的基礎 HttpMessageHandler,例如HttpClientHandler
。GrpcWebMode
:列舉型別,指定 gRPC HTTP 要求Content-Type
為application/grpc-web
或application/grpc-web-text
。GrpcWebMode.GrpcWeb
會設定傳送內容而不使用編碼。 預設值。GrpcWebMode.GrpcWebText
會設定 base64 編碼的內容。 在瀏覽器中的伺服器串流呼叫是必要的。
HttpVersion
:用來在基礎 gRPC HTTP 要求上設定 HttpRequestMessage.Version 的 HTTP 通訊協定Version
。 gRPC-Web 不需要特定版本,而且除非指定,否則不會覆寫預設值。
重要
產生的 gRPC 用戶端具有同步和非同步方法來呼叫一元方法。 例如,SayHello
是同步,而 SayHelloAsync
是非同步。 在 Blazor WebAssembly 中一律需要非同步方法。 在 Blazor WebAssembly 應用程式中呼叫同步方法會導致應用程式變得沒有回應。
搭配 gRPC-Web 使用 gRPC 用戶端 Factory
使用 gRPC 用戶端 Factory 建立與 gRPC-Web 相容的 .NET 用戶端:
- 將套件參考新增至下列套件的專案檔:
- 使用泛型
AddGrpcClient
擴充方法向相依性插入 (DI) 註冊 gRPC 用戶端。 在應用程式 Blazor WebAssembly 中,服務會在Program.cs
中向 DI 註冊。 - 使用 ConfigurePrimaryHttpMessageHandler 擴充方法設定
GrpcWebHandler
。
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
如需詳細資訊,請參閱 .NET 中的 gRPC 用戶端 Factory 整合。