針對 .NET 上的 gRPC 進行疑難排解
注意
這不是本文的最新版本。 若要切換至最新版本,請使用目錄頂端 ASP.NET Core版本選取器。
如果選取器在窄瀏覽器視窗中看不到,請擴大視窗,或選取垂直省略號 (⋮) >目錄。
本檔討論在 .NET 上開發 gRPC 應用程式時常見的問題。
用戶端和服務 SSL/TLS 組態不符
gRPC 範本和範例預設會使用 傳輸層安全性 (TLS) 來保護 gRPC 服務。 gRPC 用戶端必須使用安全連線,才能成功呼叫受保護的 gRPC 服務。
您可以在應用程式啟動時寫入的記錄中使用 TLS,確認 gRPC 服務 ASP.NET Core。 服務將在 HTTPS 端點上接聽:
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
.NET Core 用戶端必須在伺服器位址中使用 https
,才能使用安全連線進行呼叫:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
所有 gRPC 用戶端實作都支援 TLS。 來自其他語言的 gRPC 用戶端通常需要使用 設定的 SslCredentials
通道。 SslCredentials
指定用戶端將使用的憑證,而且必須使用憑證,而不是不安全的認證。 如需將不同 gRPC 用戶端實作設定為使用 TLS 的範例,請參閱 gRPC 驗證。
使用不受信任的/無效憑證呼叫 gRPC 服務
.NET gRPC 用戶端要求服務具有受信任的憑證。 呼叫不含受信任憑證的 gRPC 服務時,會傳回下列錯誤訊息:
未處理的例外狀況。 System.Net.Http.HttpRequestException:無法建立 SSL 連線,請參閱內部例外狀況。 --- > System.Security.Authentication.AuthenticationException:根據驗證程式,遠端憑證無效。
如果您要在本機測試應用程式,且 ASP.NET Core HTTPS 開發憑證不受信任,您可能會看到此錯誤。 如需修正此問題的指示,請參閱信任 Windows 和 macOS上的 ASP.NET Core HTTPS 開發憑證。
如果您要在另一部電腦上呼叫 gRPC 服務,而且無法信任憑證,則可以將 gRPC 用戶端設定為忽略不正確憑證。 下列程式碼會使用 HttpClientHandler.ServerCertificateCustomValidationCallback 來允許沒有受信任憑證的呼叫:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
gRPC 用戶端處理站允許在沒有受信任憑證的情況下呼叫。 ConfigurePrimaryHttpMessageHandler使用擴充方法在用戶端上設定處理常式:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
警告
不受信任的憑證應該只在應用程式開發期間使用。 生產應用程式應該一律使用有效的憑證。
使用 .NET Core 用戶端呼叫不安全的 gRPC 服務
.NET gRPC 用戶端可以藉由在 http
伺服器位址中指定來呼叫不安全的 gRPC 服務。 例如: GrpcChannel.ForAddress("http://localhost:5000")
。
根據應用程式正在使用的 .NET 版本,呼叫不安全的 gRPC 服務有一些額外需求:
.NET 5 或更新版本需要 Grpc.Net.Client 2.32.0 版或更新版本。
.NET Core 3.x 需要額外的設定。 應用程式必須將 參數設定
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
為true
:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
只有 .NET Core 3.x 才需要參數。 它不會在 .NET 5 中執行任何動作,而且不需要。
重要
不安全的 gRPC 服務必須裝載于僅限 HTTP/2 的埠上。 如需詳細資訊,請參閱ASP.NET Core通訊協定交涉。
無法在 macOS 上啟動 ASP.NET Core gRPC 應用程式
Kestrel 在 .NET 8 之前,不支援在 macOS 上使用 TLS 的 HTTP/2。 ASP.NET Core gRPC 範本和範例預設會使用 TLS。 當您嘗試啟動 gRPC 伺服器時,您會看到下列錯誤訊息:
無法在 IPv4 回送介面上系結至 https://localhost:5001 :「macOS 不支援 HTTP/2 over TLS,因為缺少 ALPN 支援。」。
若要在 .NET 7 和更早版本中解決此問題,請將 Kestrel 和 gRPC 用戶端設定為 不使用 TLS 的 HTTP/2。 您應該只在開發期間執行此動作。 不使用 TLS 會導致 gRPC 訊息在沒有加密的情況下傳送。
Kestrel 必須在 中 Program.cs
設定不含 TLS 的 HTTP/2 端點:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(<5287>, o => o.Protocols =
HttpProtocols.Http2);
});
- 在上述程式碼中,將 localhost 埠號碼
5287
取代為HTTP
gRPC 服務專案中指定的Properties/launchSettings.json
(未HTTPS
) 埠號碼。
在沒有 TLS 的情況下設定 HTTP/2 端點時,端點的 ListenOptions.Protocols 必須設定為 HttpProtocols.Http2
。 HttpProtocols.Http1AndHttp2
無法使用,因為需要 TLS 才能交涉 HTTP/2。 如果沒有 TLS,端點的所有連線都會預設為 HTTP/1.1,而 gRPC 呼叫會失敗。
gRPC 用戶端也必須設定為不使用 TLS。 如需詳細資訊,請參閱 使用 .NET Core 用戶端呼叫不安全的 gRPC 服務。
警告
不含 TLS 的 HTTP/2 應該只在應用程式開發期間使用。 生產應用程式應該一律使用傳輸安全性。 如需詳細資訊,請參閱gRPC 中適用于 ASP.NET Core 的安全性考慮。
gRPC C# 資產不是從 .proto
檔案產生的程式碼
gRPC 程式碼產生具體用戶端和服務基類需要從專案參考 protobuf 檔案和工具。 您必須包含:
.proto
您想要在專案群組中使用的<Protobuf>
檔案。 專案必須參考匯入.proto
的檔案。- gRPC 工具套件 Grpc.Tools的套件參考。
如需產生 gRPC C# 資產的詳細資訊,請參閱 使用 C# 的 gRPC 服務。
裝載 gRPC 服務的 ASP.NET Core Web 應用程式只需要產生的服務基類:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
進行 gRPC 呼叫的 gRPC 用戶端應用程式只需要產生的具體用戶端:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
WPF 專案無法從 .proto
檔案產生 gRPC C# 資產
WPF 專案有 已知問題 ,導致 gRPC 程式碼產生無法正常運作。 參考 Grpc.Tools
.proto
和 檔案時,在 WPF 專案中產生的任何 gRPC 類型都會在使用時建立編譯錯誤:
錯誤 CS0246:找不到類型或命名空間名稱 'MyGrpcServices', (遺漏 using 指示詞或元件參考嗎?)
您可以透過下列方式解決此問題:
- 建立新的 .NET Core 類別庫專案。
- 在新專案中,新增參考以 啟用檔案的
.proto
C# 程式碼產生:- 新增下列套件參考:
- 將
.proto
檔案新增至<Protobuf>
項目群組。
- 在 WPF 應用程式中,新增新專案的參考。
WPF 應用程式可以使用來自新類別庫專案的 gRPC 產生的類型。
呼叫裝載于子目錄中的 gRPC 服務
警告
許多協力廠商 gRPC 工具不支援子目錄中裝載的服務。 請考慮尋找將 gRPC 裝載為根目錄的方法。
進行 gRPC 呼叫時,會忽略 gRPC 通道位址的路徑元件。 例如, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
不會在路由傳送服務的 gRPC 呼叫時使用 ignored_path
。
因為 gRPC 具有標準化、規範的位址結構,所以會忽略位址路徑。 gRPC 位址結合了封裝、服務和方法名稱: https://localhost:5001/PackageName.ServiceName/MethodName
。
在某些情況下,應用程式需要包含具有 gRPC 呼叫的路徑。 例如,當 ASP.NET Core gRPC 應用程式裝載于 IIS 目錄中,且要求中必須包含目錄時。 需要路徑時,可以使用下列自訂的指定 SubdirectoryHandler
,將其新增至 gRPC 呼叫:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
會在建立 gRPC 通道時使用。
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
上述程式碼:
SubdirectoryHandler
使用路徑/MyApp
建立 。- 設定通道以使用
SubdirectoryHandler
。 - 使用
SayHelloAsync
呼叫 gRPC 服務。 gRPC 呼叫會傳送至https://localhost:5001/MyApp/greet.Greeter/SayHello
。
或者,可以使用 SubdirectoryHandler
來設定 AddHttpMessageHandler 用戶端處理站。
將 gRPC 用戶端設定為使用 HTTP/3
.NET gRPC 用戶端支援 HTTP/3 與 .NET 6 或更新版本。 如果伺服器將回應標頭傳送 alt-svc
至指出伺服器支援 HTTP/3 的用戶端,用戶端會自動將其連線升級至 HTTP/3。 伺服器 Kestrel 預設支援 HTTP/3。 如需詳細資訊,請參閱搭配 ASP.NET Core Kestrel 網頁伺服器使用 HTTP/3。
DelegatingHandler可用來強制 gRPC 用戶端使用 HTTP/3。 強制 HTTP/3 可避免升級要求的額外負荷。 強制使用類似下列程式碼的 HTTP/3:
/// <summary>
/// A delegating handler that changes the request HTTP version to HTTP/3.
/// </summary>
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler
會在建立 gRPC 通道時使用。 下列程式碼會建立設定為使用 的 Http3Handler
通道。
var handler = new Http3Handler(new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
或者,可以使用 Http3Handler
來設定 AddHttpMessageHandler 用戶端處理站。
在 Alpine Linux 上建置 gRPC
套件 Grpc.Tools
會使用稱為 protoc
的配套原生二進位檔,從 .proto
檔案產生 .NET 類型。 在 中原生二進位檔 Grpc.Tools
不支援的平臺上建置 gRPC 應用程式,例如 Alpine Linux 所需的額外步驟。
事先產生程式碼
其中一個解決方案是事先產生程式碼。
- 將檔案和
Grpc.Tools
套件參考移至.proto
新專案。 - 將專案發佈為 NuGet 套件,並將其上傳至 NuGet 摘要。
- 更新應用程式以參考 NuGet 套件。
在上述步驟中,應用程式不再需要 Grpc.Tools
建置,因為程式碼會事先產生。
自訂 Grpc.Tools
原生二進位檔
Grpc.Tools
支援使用自訂原生二進位檔。 此功能可讓 gRPC 工具在其配套的原生二進位檔不支援的環境中執行。
建置或取得 protoc
和 grpc_csharp_plugin
原生二進位檔,並將其設定 Grpc.Tools
為使用這些二進位檔。 藉由設定下列環境變數來設定原生二進位檔:
PROTOBUF_PROTOC
- 通訊協定緩衝區編譯器的完整路徑GRPC_PROTOC_PLUGIN
- grpc_csharp_plugin的完整路徑
針對 Alpine Linux,在 上提供通訊協定緩衝區編譯器和 gRPC 外掛程式的社群提供套件 https://pkgs.alpinelinux.org/ 。
# Build or install the binaries for your architecture.
# e.g. for Alpine Linux the grpc-plugins package can be used
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
如需搭配不支援架構使用 Grpc.Tools
的詳細資訊,請參閱 gRPC 組建整合檔。
本檔討論在 .NET 上開發 gRPC 應用程式時常見的問題。
用戶端和服務 SSL/TLS 組態不符
gRPC 範本和範例預設會使用 傳輸層安全性 (TLS) 來保護 gRPC 服務。 gRPC 用戶端必須使用安全連線,才能成功呼叫受保護的 gRPC 服務。
您可以在應用程式啟動時寫入的記錄中使用 TLS,確認 gRPC 服務 ASP.NET Core。 服務將在 HTTPS 端點上接聽:
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
.NET Core 用戶端必須在伺服器位址中使用 https
,才能使用安全連線進行呼叫:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
所有 gRPC 用戶端實作都支援 TLS。 來自其他語言的 gRPC 用戶端通常需要使用 設定的 SslCredentials
通道。 SslCredentials
指定用戶端將使用的憑證,而且必須使用憑證,而不是不安全的認證。 如需將不同 gRPC 用戶端實作設定為使用 TLS 的範例,請參閱 gRPC 驗證。
使用不受信任的/無效憑證呼叫 gRPC 服務
.NET gRPC 用戶端要求服務具有受信任的憑證。 呼叫不含受信任憑證的 gRPC 服務時,會傳回下列錯誤訊息:
未處理的例外狀況。 System.Net.Http.HttpRequestException:無法建立 SSL 連線,請參閱內部例外狀況。 --- > System.Security.Authentication.AuthenticationException:根據驗證程式,遠端憑證無效。
如果您要在本機測試應用程式,且 ASP.NET Core HTTPS 開發憑證不受信任,您可能會看到此錯誤。 如需修正此問題的指示,請參閱信任 Windows 和 macOS上的 ASP.NET Core HTTPS 開發憑證。
如果您要在另一部電腦上呼叫 gRPC 服務,而且無法信任憑證,則可以將 gRPC 用戶端設定為忽略不正確憑證。 下列程式碼會使用 HttpClientHandler.ServerCertificateCustomValidationCallback 來允許沒有受信任憑證的呼叫:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
gRPC 用戶端處理站允許在沒有受信任憑證的情況下呼叫。 ConfigurePrimaryHttpMessageHandler使用擴充方法在用戶端上設定處理常式:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
警告
不受信任的憑證應該只在應用程式開發期間使用。 生產應用程式應該一律使用有效的憑證。
使用 .NET Core 用戶端呼叫不安全的 gRPC 服務
.NET gRPC 用戶端可以藉由在 http
伺服器位址中指定來呼叫不安全的 gRPC 服務。 例如: GrpcChannel.ForAddress("http://localhost:5000")
。
根據應用程式正在使用的 .NET 版本,呼叫不安全的 gRPC 服務有一些額外需求:
.NET 5 或更新版本需要 Grpc.Net.Client 2.32.0 版或更新版本。
.NET Core 3.x 需要額外的設定。 應用程式必須將 參數設定
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
為true
:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
只有 .NET Core 3.x 才需要參數。 它不會在 .NET 5 中執行任何動作,而且不需要。
重要
不安全的 gRPC 服務必須裝載于僅限 HTTP/2 的埠上。 如需詳細資訊,請參閱ASP.NET Core通訊協定交涉。
無法在 macOS 上啟動 ASP.NET Core gRPC 應用程式
Kestrel 在 .NET 8 之前,不支援在 macOS 上使用 TLS 的 HTTP/2。 ASP.NET Core gRPC 範本和範例預設會使用 TLS。 當您嘗試啟動 gRPC 伺服器時,您會看到下列錯誤訊息:
無法在 IPv4 回送介面上系結至 https://localhost:5001 :「macOS 不支援 HTTP/2 over TLS,因為缺少 ALPN 支援。」。
若要在 .NET 7 和更早版本中解決此問題,請將 Kestrel 和 gRPC 用戶端設定為 不使用 TLS 的 HTTP/2。 您應該只在開發期間執行此動作。 不使用 TLS 會導致 gRPC 訊息在沒有加密的情況下傳送。
Kestrel 必須在 中 Program.cs
設定不含 TLS 的 HTTP/2 端點:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(<5287>, o => o.Protocols =
HttpProtocols.Http2);
});
- 在上述程式碼中,將 localhost 埠號碼
5287
取代為HTTP
gRPC 服務專案中指定的Properties/launchSettings.json
(未HTTPS
) 埠號碼。
在沒有 TLS 的情況下設定 HTTP/2 端點時,端點的 ListenOptions.Protocols 必須設定為 HttpProtocols.Http2
。 HttpProtocols.Http1AndHttp2
無法使用,因為需要 TLS 才能交涉 HTTP/2。 如果沒有 TLS,端點的所有連線都會預設為 HTTP/1.1,而 gRPC 呼叫會失敗。
gRPC 用戶端也必須設定為不使用 TLS。 如需詳細資訊,請參閱 使用 .NET Core 用戶端呼叫不安全的 gRPC 服務。
警告
不含 TLS 的 HTTP/2 應該只在應用程式開發期間使用。 生產應用程式應該一律使用傳輸安全性。 如需詳細資訊,請參閱gRPC 中適用于 ASP.NET Core 的安全性考慮。
gRPC C# 資產不是從 .proto
檔案產生的程式碼
gRPC 程式碼產生具體用戶端和服務基類需要從專案參考 protobuf 檔案和工具。 您必須包含:
.proto
您想要在專案群組中使用的<Protobuf>
檔案。 專案必須參考匯入.proto
的檔案。- gRPC 工具套件 Grpc.Tools的套件參考。
如需產生 gRPC C# 資產的詳細資訊,請參閱 使用 C# 的 gRPC 服務。
裝載 gRPC 服務的 ASP.NET Core Web 應用程式只需要產生的服務基類:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
進行 gRPC 呼叫的 gRPC 用戶端應用程式只需要產生的具體用戶端:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
WPF 專案無法從 .proto
檔案產生 gRPC C# 資產
WPF 專案有 已知問題 ,導致 gRPC 程式碼產生無法正常運作。 參考 Grpc.Tools
.proto
和 檔案時,在 WPF 專案中產生的任何 gRPC 類型都會在使用時建立編譯錯誤:
錯誤 CS0246:找不到類型或命名空間名稱 'MyGrpcServices', (遺漏 using 指示詞或元件參考嗎?)
您可以透過下列方式解決此問題:
- 建立新的 .NET Core 類別庫專案。
- 在新專案中,新增參考以 啟用檔案的
.proto
C# 程式碼產生:- 新增下列套件參考:
- 將
.proto
檔案新增至<Protobuf>
項目群組。
- 在 WPF 應用程式中,新增新專案的參考。
WPF 應用程式可以使用來自新類別庫專案的 gRPC 產生的類型。
呼叫裝載于子目錄中的 gRPC 服務
警告
許多協力廠商 gRPC 工具不支援子目錄中裝載的服務。 請考慮尋找將 gRPC 裝載為根目錄的方法。
進行 gRPC 呼叫時,會忽略 gRPC 通道位址的路徑元件。 例如, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
不會在路由傳送服務的 gRPC 呼叫時使用 ignored_path
。
因為 gRPC 具有標準化、規範的位址結構,所以會忽略位址路徑。 gRPC 位址結合了封裝、服務和方法名稱: https://localhost:5001/PackageName.ServiceName/MethodName
。
在某些情況下,應用程式需要包含具有 gRPC 呼叫的路徑。 例如,當 ASP.NET Core gRPC 應用程式裝載于 IIS 目錄中,且要求中必須包含目錄時。 需要路徑時,可以使用下列自訂的指定 SubdirectoryHandler
,將其新增至 gRPC 呼叫:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
會在建立 gRPC 通道時使用。
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
上述程式碼:
SubdirectoryHandler
使用路徑/MyApp
建立 。- 設定通道以使用
SubdirectoryHandler
。 - 使用
SayHelloAsync
呼叫 gRPC 服務。 gRPC 呼叫會傳送至https://localhost:5001/MyApp/greet.Greeter/SayHello
。
或者,可以使用 SubdirectoryHandler
來設定 AddHttpMessageHandler 用戶端處理站。
將 gRPC 用戶端設定為使用 HTTP/3
.NET gRPC 用戶端支援 HTTP/3 與 .NET 6 或更新版本。 如果伺服器將回應標頭傳送 alt-svc
至指出伺服器支援 HTTP/3 的用戶端,用戶端會自動將其連線升級至 HTTP/3。 如需如何在伺服器上啟用 HTTP/3 的資訊,請參閱搭配 ASP.NET Core Kestrel Web 服務器使用 HTTP/3。
預設會啟用 .NET 8 中的 HTTP/3 支援。 .NET 6 和 .NET 7 中的 HTTP/3 支援必須透過專案檔中的組態旗標來啟用:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
System.Net.SocketsHttpHandler.Http3Support
也可以使用 AppCoNtext.SetSwitch 來設定。
DelegatingHandler可用來強制 gRPC 用戶端使用 HTTP/3。 強制 HTTP/3 可避免升級要求的額外負荷。 強制使用類似下列程式碼的 HTTP/3:
/// <summary>
/// A delegating handler that changes the request HTTP version to HTTP/3.
/// </summary>
public class Http3Handler : DelegatingHandler
{
public Http3Handler() { }
public Http3Handler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = HttpVersion.Version30;
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;
return base.SendAsync(request, cancellationToken);
}
}
Http3Handler
會在建立 gRPC 通道時使用。 下列程式碼會建立設定為使用 的 Http3Handler
通道。
var handler = new Http3Handler(new HttpClientHandler());
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
或者,可以使用 Http3Handler
來設定 AddHttpMessageHandler 用戶端處理站。
在 Alpine Linux 上建置 gRPC
套件 Grpc.Tools
會使用稱為 protoc
的配套原生二進位檔,從 .proto
檔案產生 .NET 類型。 在 中原生二進位檔 Grpc.Tools
不支援的平臺上建置 gRPC 應用程式,例如 Alpine Linux 所需的額外步驟。
事先產生程式碼
其中一個解決方案是事先產生程式碼。
- 將檔案和
Grpc.Tools
套件參考移至.proto
新專案。 - 將專案發佈為 NuGet 套件,並將其上傳至 NuGet 摘要。
- 更新應用程式以參考 NuGet 套件。
在上述步驟中,應用程式不再需要 Grpc.Tools
建置,因為程式碼會事先產生。
自訂 Grpc.Tools
原生二進位檔
Grpc.Tools
支援使用自訂原生二進位檔。 此功能可讓 gRPC 工具在其配套的原生二進位檔不支援的環境中執行。
建置或取得 protoc
和 grpc_csharp_plugin
原生二進位檔,並將其設定 Grpc.Tools
為使用這些二進位檔。 藉由設定下列環境變數來設定原生二進位檔:
PROTOBUF_PROTOC
- 通訊協定緩衝區編譯器的完整路徑GRPC_PROTOC_PLUGIN
- grpc_csharp_plugin的完整路徑
針對 Alpine Linux,在 上提供通訊協定緩衝區編譯器和 gRPC 外掛程式的社群提供套件 https://pkgs.alpinelinux.org/ 。
# Build or install the binaries for your architecture.
# e.g. for Alpine Linux the grpc-plugins package can be used
# See https://pkgs.alpinelinux.org/package/edge/community/x86_64/grpc-plugins
apk add grpc-plugins # Alpine Linux specific package installer
# Set environment variables for the built/installed protoc
# and grpc_csharp_plugin binaries
export PROTOBUF_PROTOC=/usr/bin/protoc
export GRPC_PROTOC_PLUGIN=/usr/bin/grpc_csharp_plugin
# When dotnet build runs, the Grpc.Tools NuGet package
# uses the binaries pointed to by the environment variables.
dotnet build
如需搭配不支援架構使用 Grpc.Tools
的詳細資訊,請參閱 gRPC 組建整合檔。
本檔討論在 .NET 上開發 gRPC 應用程式時常見的問題。
用戶端和服務 SSL/TLS 組態不符
gRPC 範本和範例預設會使用 傳輸層安全性 (TLS) 來保護 gRPC 服務。 gRPC 用戶端必須使用安全連線,才能成功呼叫受保護的 gRPC 服務。
您可以在應用程式啟動時寫入的記錄中使用 TLS,確認 gRPC 服務 ASP.NET Core。 服務將在 HTTPS 端點上接聽:
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
.NET Core 用戶端必須在伺服器位址中使用 https
,才能使用安全連線進行呼叫:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
所有 gRPC 用戶端實作都支援 TLS。 來自其他語言的 gRPC 用戶端通常需要使用 設定的 SslCredentials
通道。 SslCredentials
指定用戶端將使用的憑證,而且必須使用憑證,而不是不安全的認證。 如需將不同 gRPC 用戶端實作設定為使用 TLS 的範例,請參閱 gRPC 驗證。
使用不受信任的/無效憑證呼叫 gRPC 服務
.NET gRPC 用戶端要求服務具有受信任的憑證。 呼叫不含受信任憑證的 gRPC 服務時,會傳回下列錯誤訊息:
未處理的例外狀況。 System.Net.Http.HttpRequestException:無法建立 SSL 連線,請參閱內部例外狀況。 --- > System.Security.Authentication.AuthenticationException:根據驗證程式,遠端憑證無效。
如果您要在本機測試應用程式,且 ASP.NET Core HTTPS 開發憑證不受信任,您可能會看到此錯誤。 如需修正此問題的指示,請參閱信任 Windows 和 macOS上的 ASP.NET Core HTTPS 開發憑證。
如果您要在另一部電腦上呼叫 gRPC 服務,而且無法信任憑證,則可以將 gRPC 用戶端設定為忽略不正確憑證。 下列程式碼會使用 HttpClientHandler.ServerCertificateCustomValidationCallback 來允許沒有受信任憑證的呼叫:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
gRPC 用戶端處理站允許在沒有受信任憑證的情況下呼叫。 ConfigurePrimaryHttpMessageHandler使用擴充方法在用戶端上設定處理常式:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
警告
不受信任的憑證應該只在應用程式開發期間使用。 生產應用程式應該一律使用有效的憑證。
使用 .NET Core 用戶端呼叫不安全的 gRPC 服務
.NET gRPC 用戶端可以藉由在 http
伺服器位址中指定來呼叫不安全的 gRPC 服務。 例如: GrpcChannel.ForAddress("http://localhost:5000")
。
根據應用程式正在使用的 .NET 版本,呼叫不安全的 gRPC 服務有一些額外需求:
.NET 5 或更新版本需要 Grpc.Net.Client 2.32.0 版或更新版本。
.NET Core 3.x 需要額外的設定。 應用程式必須將 參數設定
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
為true
:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
只有 System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
.NET Core 3.x 才需要參數。 它不會在 .NET 5 中執行任何動作,而且不需要。
重要
不安全的 gRPC 服務必須裝載于僅限 HTTP/2 的埠上。 如需詳細資訊,請參閱ASP.NET Core通訊協定交涉。
無法在 macOS 上啟動 ASP.NET Core gRPC 應用程式
Kestrel 在 .NET 8 之前,不支援在 macOS 上使用 TLS 的 HTTP/2。 ASP.NET Core gRPC 範本和範例預設會使用 TLS。 當您嘗試啟動 gRPC 伺服器時,您會看到下列錯誤訊息:
無法在 IPv4 回送介面上系結至 https://localhost:5001 :「macOS 不支援 HTTP/2 over TLS,因為缺少 ALPN 支援。」。
若要在 .NET 7 和更早版本中解決此問題,請將 和 gRPC 用戶端設定 Kestrel 為在沒有 TLS 的情況下 使用 HTTP/2。 您應該只在開發期間執行此動作。 不使用 TLS 會導致 gRPC 訊息在未加密的情況下傳送。
Kestrel 必須在 中 Program.cs
設定不含 TLS 的 HTTP/2 端點:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5000, o => o.Protocols =
HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});
在沒有 TLS 的情況下設定 HTTP/2 端點時,端點的 ListenOptions.Protocols 必須設定為 HttpProtocols.Http2
。 HttpProtocols.Http1AndHttp2
無法使用,因為需要 TLS 才能交涉 HTTP/2。 如果沒有 TLS,端點的所有連線都會預設為 HTTP/1.1,而 gRPC 呼叫會失敗。
gRPC 用戶端也必須設定為不使用 TLS。 如需詳細資訊,請參閱 使用 .NET Core 用戶端呼叫不安全的 gRPC 服務。
警告
不含 TLS 的 HTTP/2 應該只在應用程式開發期間使用。 生產應用程式應該一律使用傳輸安全性。 如需詳細資訊,請參閱gRPC 中適用于 ASP.NET Core 的安全性考慮。
gRPC C# 資產不是從 .proto
檔案產生的程式碼
gRPC 程式碼產生具象用戶端和服務基類需要從專案參考 protobuf 檔案和工具。 您必須包含:
.proto
您想要在專案群組中使用的<Protobuf>
檔案。 專案必須參考匯入的.proto
檔案。- gRPC 工具套件 Grpc.Tools的套件參考。
如需產生 gRPC C# 資產的詳細資訊,請參閱 使用 C# 的 gRPC 服務。
裝載 gRPC 服務的 ASP.NET Core Web 應用程式只需要產生的服務基類:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
進行 gRPC 呼叫的 gRPC 用戶端應用程式只需要產生的具體用戶端:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
WPF 專案無法從 .proto
檔案產生 gRPC C# 資產
WPF 專案有 已知問題 ,可防止 gRPC 程式碼產生正常運作。 參考 Grpc.Tools
.proto
和檔案會在使用時,在 WPF 專案中產生的任何 gRPC 類型都會建立編譯錯誤:
錯誤 CS0246:找不到類型或命名空間名稱 'MyGrpcServices', (遺漏 using 指示詞或元件參考?)
您可以透過下列方式解決此問題:
- 建立新的 .NET Core 類別庫專案。
- 在新專案中,新增參考以 啟用從
.proto
檔案產生 C# 程式碼:- 新增下列套件參考:
- 將
.proto
檔案新增至<Protobuf>
項目群組。
- 在 WPF 應用程式中,新增新專案的參考。
WPF 應用程式可以使用新類別庫專案中產生的 gRPC 型別。
呼叫裝載在子目錄中的 gRPC 服務
警告
許多協力廠商 gRPC 工具不支援子目錄中裝載的服務。 請考慮尋找將 gRPC 裝載為根目錄的方法。
進行 gRPC 呼叫時,會忽略 gRPC 通道位址的路徑元件。 例如, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
在路由 gRPC 呼叫服務時,不會使用 ignored_path
。
因為 gRPC 具有標準化、規範的位址結構,所以會忽略位址路徑。 gRPC 位址結合了封裝、服務和方法名稱: https://localhost:5001/PackageName.ServiceName/MethodName
。
當應用程式需要包含 gRPC 呼叫的路徑時,有一些案例。 例如,當 ASP.NET Core gRPC 應用程式裝載于 IIS 目錄中,且該目錄必須包含在要求中時。 需要路徑時,可以使用下列自訂 SubdirectoryHandler
新增至 gRPC 呼叫:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
會在建立 gRPC 通道時使用。
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
上述程式碼:
SubdirectoryHandler
使用路徑/MyApp
建立 。- 設定通道以使用
SubdirectoryHandler
。 - 使用
SayHelloAsync
呼叫 gRPC 服務。 gRPC 呼叫會傳送至https://localhost:5001/MyApp/greet.Greeter/SayHello
。
或者,您可以使用 SubdirectoryHandler
AddHttpMessageHandler 來設定用戶端處理站。
本檔討論在 .NET 上開發 gRPC 應用程式時常見的問題。
用戶端和服務 SSL/TLS 組態不符
gRPC 範本和範例預設會使用 傳輸層安全性 (TLS) 來保護 gRPC 服務。 gRPC 用戶端需要使用安全連線,才能成功呼叫受保護的 gRPC 服務。
您可以在應用程式啟動時寫入的記錄中,確認 gRPC 服務 ASP.NET Core使用 TLS。 服務將在 HTTPS 端點上接聽:
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
.NET Core 用戶端必須在 https
伺服器位址中使用 ,才能使用安全連線進行呼叫:
static async Task Main(string[] args)
{
// The port number(5001) must match the port of the gRPC server.
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new Greet.GreeterClient(channel);
}
所有 gRPC 用戶端實作都支援 TLS。 來自其他語言的 gRPC 用戶端通常需要使用 設定的 SslCredentials
通道。 SslCredentials
會指定用戶端將使用的憑證,而且必須使用它,而不是不安全的認證。 如需設定不同 gRPC 用戶端實作以使用 TLS 的範例,請參閱 gRPC 驗證。
使用不受信任/不正確憑證呼叫 gRPC 服務
.NET gRPC 用戶端需要服務具有受信任的憑證。 呼叫不含受信任憑證的 gRPC 服務時,會傳回下列錯誤訊息:
未處理的例外狀況。 System.Net.Http.HttpRequestException:無法建立 SSL 連線,請參閱內部例外狀況。 --- > System.Security.Authentication.AuthenticationException:根據驗證程式,遠端憑證無效。
如果您要在本機測試應用程式,且 ASP.NET Core HTTPS 開發憑證不受信任,您可能會看到此錯誤。 如需修正此問題的指示,請參閱信任 Windows 和 macOS上的 ASP.NET Core HTTPS 開發憑證。
如果您要在另一部電腦上呼叫 gRPC 服務,而且無法信任憑證,則可以將 gRPC 用戶端設定為忽略不正確憑證。 下列程式碼會使用 HttpClientHandler.ServerCertificateCustomValidationCallback 來允許沒有受信任憑證的呼叫:
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
gRPC 用戶端處理站允許呼叫,而不需要受信任的憑證。 ConfigurePrimaryHttpMessageHandler使用擴充方法在用戶端上設定處理常式:
services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
return handler;
});
警告
不受信任的憑證只能在應用程式開發期間使用。 生產應用程式應該一律使用有效的憑證。
使用 .NET Core 用戶端呼叫不安全的 gRPC 服務
.NET gRPC 用戶端可以藉由在伺服器位址中指定 http
來呼叫不安全的 gRPC 服務。 例如: GrpcChannel.ForAddress("http://localhost:5000")
。
視應用程式正在使用的 .NET 版本而定,呼叫不安全的 gRPC 服務有一些額外需求:
.NET 5 或更新版本需要 Grpc.Net.Client 2.32.0 版或更新版本。
.NET Core 3.x 需要額外的設定。 應用程式必須將 參數設定
System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
為true
:// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch( "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); // The port number(5000) must match the port of the gRPC server. var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new Greet.GreeterClient(channel);
只有 System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport
.NET Core 3.x 才需要參數。 它不會在 .NET 5 中執行任何動作,而且不需要。
重要
不安全的 gRPC 服務必須裝載于僅限 HTTP/2 的埠上。 如需詳細資訊,請參閱ASP.NET Core通訊協定交涉。
無法在 macOS 上啟動 ASP.NET Core gRPC 應用程式
Kestrel 在 .NET 8 之前,不支援在 macOS 上使用 TLS 的 HTTP/2。 ASP.NET Core gRPC 範本和範例預設會使用 TLS。 當您嘗試啟動 gRPC 伺服器時,您會看到下列錯誤訊息:
無法在 IPv4 回送介面上系結至 https://localhost:5001 :「macOS 不支援 HTTP/2 over TLS,因為缺少 ALPN 支援。」。
若要在 .NET 7 和更早版本中解決此問題,請將 和 gRPC 用戶端設定 Kestrel 為在沒有 TLS 的情況下 使用 HTTP/2。 您應該只在開發期間執行此動作。 不使用 TLS 會導致 gRPC 訊息在未加密的情況下傳送。
Kestrel 必須在 中 Program.cs
設定不含 TLS 的 HTTP/2 端點:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5000, o => o.Protocols =
HttpProtocols.Http2);
});
webBuilder.UseStartup<Startup>();
});
在沒有 TLS 的情況下設定 HTTP/2 端點時,端點的 ListenOptions.Protocols 必須設定為 HttpProtocols.Http2
。 HttpProtocols.Http1AndHttp2
無法使用,因為需要 TLS 才能交涉 HTTP/2。 如果沒有 TLS,端點的所有連線都會預設為 HTTP/1.1,而 gRPC 呼叫會失敗。
gRPC 用戶端也必須設定為不使用 TLS。 如需詳細資訊,請參閱 使用 .NET Core 用戶端呼叫不安全的 gRPC 服務。
警告
不含 TLS 的 HTTP/2 應該只在應用程式開發期間使用。 生產應用程式應該一律使用傳輸安全性。 如需詳細資訊,請參閱gRPC 中適用于 ASP.NET Core 的安全性考慮。
gRPC C# 資產不是從 .proto
檔案產生的程式碼
gRPC 程式碼產生具象用戶端和服務基類需要從專案參考 protobuf 檔案和工具。 您必須包含:
.proto
您想要在專案群組中使用的<Protobuf>
檔案。 專案必須參考匯入的.proto
檔案。- gRPC 工具套件 Grpc.Tools的套件參考。
如需產生 gRPC C# 資產的詳細資訊,請參閱 使用 C# 的 gRPC 服務。
裝載 gRPC 服務的 ASP.NET Core Web 應用程式只需要產生的服務基類:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
進行 gRPC 呼叫的 gRPC 用戶端應用程式只需要產生的具體用戶端:
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>
WPF 專案無法從 .proto
檔案產生 gRPC C# 資產
WPF 專案有 已知問題 ,可防止 gRPC 程式碼產生正常運作。 參考 Grpc.Tools
.proto
和檔案會在使用時,在 WPF 專案中產生的任何 gRPC 類型都會建立編譯錯誤:
錯誤 CS0246:找不到類型或命名空間名稱 'MyGrpcServices', (遺漏 using 指示詞或元件參考?)
您可以透過下列方式解決此問題:
- 建立新的 .NET Core 類別庫專案。
- 在新專案中,新增參考以 啟用從
.proto
檔案產生 C# 程式碼:- 新增下列套件參考:
- 將
.proto
檔案新增至<Protobuf>
項目群組。
- 在 WPF 應用程式中,新增新專案的參考。
WPF 應用程式可以使用新類別庫專案中產生的 gRPC 型別。
呼叫裝載在子目錄中的 gRPC 服務
警告
許多協力廠商 gRPC 工具不支援子目錄中裝載的服務。 請考慮尋找將 gRPC 裝載為根目錄的方法。
進行 gRPC 呼叫時,會忽略 gRPC 通道位址的路徑元件。 例如, GrpcChannel.ForAddress("https://localhost:5001/ignored_path")
在路由 gRPC 呼叫服務時,不會使用 ignored_path
。
因為 gRPC 具有標準化、規範的位址結構,所以會忽略位址路徑。 gRPC 位址結合了封裝、服務和方法名稱: https://localhost:5001/PackageName.ServiceName/MethodName
。
當應用程式需要包含 gRPC 呼叫的路徑時,有一些案例。 例如,當 ASP.NET Core gRPC 應用程式裝載于 IIS 目錄中,且該目錄必須包含在要求中時。 需要路徑時,可以使用下列自訂 SubdirectoryHandler
新增至 gRPC 呼叫:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
SubdirectoryHandler
會在建立 gRPC 通道時使用。
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/MyApp");
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions { HttpHandler = handler });
var client = new Greet.GreeterClient(channel);
var reply = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
上述程式碼:
SubdirectoryHandler
使用路徑/MyApp
建立 。- 設定通道以使用
SubdirectoryHandler
。 - 使用
SayHelloAsync
呼叫 gRPC 服務。 gRPC 呼叫會傳送至https://localhost:5001/MyApp/greet.Greeter/SayHello
。
或者,您可以使用 SubdirectoryHandler
AddHttpMessageHandler 來設定用戶端處理站。