### Start the InteropTestsWebsite Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsWebsite/README.md Run this command from the project root to start the website. It will output the listening address. ```bash # From this directory $ dotnet run Now listening on: http://localhost:50052 ``` -------------------------------- ### Install .NET Core SDK Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md Run this script before building the project to ensure the correct .NET Core SDK is installed. This is essential for developing with gRPC for ASP.NET Core. ```bash # Run this script before building the project. ./build/get-dotnet.sh or ./build/get-dotnet.ps1 ``` -------------------------------- ### Activate .NET Core SDK Environment Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md Source this script to set up your development environment to use the installed .NET Core SDK. This is a prerequisite for launching Visual Studio or building from the command line. ```bash # Source this script to use the installed .NET Core SDK. source ./activate.sh or . ./activate.ps1 ``` -------------------------------- ### Run QpsWorker in gRPC Benchmark Environment Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/README.md Starts the QpsWorker, which hosts gRPC services for benchmark servers or clients. Configure logging level and driver port as needed. ```cmd dotnet run -c Release -- --LogLevel Warning --driver_port 5000 ``` -------------------------------- ### Generate DocFX Documentation Manually Source: https://github.com/grpc/grpc-dotnet/blob/master/docfx/README.md Run this command in the root directory to generate DocFX documentation into the ./html directory. Ensure DocFX is installed according to the official instructions. ```bash # generate docfx documentation into ./html directory $ docfx ``` ```bash # view the resulting docs $ docfx server html ``` -------------------------------- ### Automate DocFX Documentation Regeneration for Release Source: https://github.com/grpc/grpc-dotnet/blob/master/docfx/README.md This script automates the regeneration of API docs using a Dockerized DocFX installation, preparing them for a PR to update the grpc.io site. It is intended to be run on Linux with Docker installed. ```bash # 1. Run the script on Linux with docker installed $ ./generate_reference_docs.sh ``` ```bash # 2. Enter the git repo with updated "gh-pages" branch $ cd grpc-gh-pages ``` ```bash # 3. Review the changes and create a pull request ``` -------------------------------- ### Coloring Icons with CSS Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Apply custom colors to specific icons by setting the 'fill' property on their respective classes. This example colors the 'account-login' icon red. ```css .icon-account-login { fill: #f00; } ``` -------------------------------- ### Server-side Error Handling in gRPC Streams Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Example C# code fragment demonstrating how a server can conditionally include a Google.Rpc.Status object in a streaming response when an error occurs during request processing. ```csharp await foreach (var request in requestStream.ReadAllAsync()) { var response = new WidgetRsp(); // ... process the request ... // to return an error if (error) { response.Status = new Google.Rpc.Status { /* ... */ }; } else { response.WidgetDetails = "the details"; } } ``` -------------------------------- ### Bi-directional Streaming Call Example Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/README.md Initiates a bi-directional streaming call, reads messages from the response stream in a background task, sends messages to the request stream, and completes the call gracefully. Use this pattern when both client and server need to send a sequence of messages. ```csharp var client = new Echo.EchoClient(channel); using var call = client.Echo(); Console.WriteLine("Starting background task to receive messages"); var readTask = Task.Run(async () => { await foreach (var response in call.ResponseStream.ReadAllAsync()) { Console.WriteLine(response.Message); // Echo messages sent to the service } }); Console.WriteLine("Starting to send messages"); Console.WriteLine("Type a message to echo then press enter."); while (true) { var result = Console.ReadLine(); if (string.IsNullOrEmpty(result)) { break; } await call.RequestStream.WriteAsync(new EchoMessage { Message = result }); } Console.WriteLine("Disconnecting"); await call.RequestStream.CompleteAsync(); await readTask; ``` -------------------------------- ### Send Unary Request to Greeter Service Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/wwwroot/index.html Use this JavaScript code to send a unary GET request to the Greeter service. The name is sent as a URL parameter. Ensure the HTML elements with IDs 'nameUnary', 'sendUnary', and 'resultUnary' exist. ```javascript var nameUnaryInput = document.getElementById('nameUnary'); var unaryForm = document.getElementById('sendUnary'); var resultUnaryText = document.getElementById('resultUnary'); unaryForm.addEventListener('submit', function (event) { if (unaryForm.checkValidity()) { resultUnaryText.innerHTML = ''; var url = '/v1/greeter/' + encodeURIComponent(nameUnaryInput.value); fetch(url).then(function (response) { response.text().then(function (data) { resultUnaryText.innerHTML = `
Request

GET ${url}

Response

HTTP/1.1 ${response.status} ${getReasonPhrase(response.status)}

${htmlEscape(data)}

Result

${JSON.parse(data).message}

`; }); }); } event.preventDefault(); event.stopPropagation(); }, false); ``` -------------------------------- ### Client-side Handling of gRPC Stream Responses with Status Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Example C# code fragment showing how a client can process a gRPC stream response, distinguishing between successful details and error statuses using a switch statement on the message case. ```csharp // reading the responses var responseReaderTask = Task.Run(async () => { await foreach (var rsp in call.ResponseStream.ReadAllAsync()) { switch (rsp.MessageCase) { case WidgetRsp.MessageOneofCase.WidgetDetails: // ... processes the details ... break; case WidgetRsp.MessageOneofCase.Status: // ... handle the error ... break; } } }); // sending the requests foreach (var request in requests) { await call.RequestStream.WriteAsync(request); } ``` -------------------------------- ### Get Test Names with gRPC-Web Mode Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsGrpcWebClient/wwwroot/index.html Retrieves the names of available tests for a specified gRPC-Web mode by invoking a method on the Blazor test helper. Ensure the test helper is initialized before calling this function. ```javascript // Get test names for the specified mode function getTestNames(grpcWebMode) { var testHelper = window.testHelper; return testHelper.invokeMethodAsync('GetTestNames', grpcWebMode); } ``` -------------------------------- ### Launch Visual Studio with SDK Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md After activating the .NET Core SDK environment, use this command to launch Visual Studio. This ensures Visual Studio uses the correct SDK for gRPC development. ```bash # activate.sh or activate.ps1 must be sourced first, see previous step startvs.cmd ``` -------------------------------- ### Run gRPC Interop Client Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsWebsite/README.md Navigate to the client's build directory and execute the client. Specify the server host, port, and the test case to run. ```bash cd src/csharp/Grpc.IntegrationTesting.Client/bin/Debug/net45 mono Grpc.IntegrationTesting.Client.exe --server_host=localhost --server_port=50052 --test_case=large_unary ``` -------------------------------- ### Build gRPC Project Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md Build the gRPC project from the command line using the dotnet CLI. Ensure the solution file path is correct. ```bash dotnet build Grpc.DotNet.slnx ``` -------------------------------- ### Build and Run gRPC-Web Client Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/README.md Instructions to build and run the gRPC-Web client using Docker Compose. The client will be accessible at http://localhost:8081. ```bash docker compose -f docker-compose.yml build grpcweb-client docker compose -f docker-compose.yml up grpcweb-client ``` -------------------------------- ### Run gRPC-dotnet Benchmark Client with Named Pipes Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/README.md Launches the gRPC client to benchmark against a server using named pipes. Requires specifying the named pipe name along with other client parameters. ```bash dotnet run -c Release --project .\perf\benchmarkapps\GrpcClient\ -- -u http://localhost:5000 -c 10 --streams 50 -s unary -p h2c --grpcClientType grpcnetclient --namedPipeName PerfPipe ``` -------------------------------- ### Run gRPC-dotnet Benchmark Client with TCP Sockets Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/README.md Launches the gRPC client to benchmark against a server using TCP sockets. Specify the server URL, connection count, stream count, scenario, protocol, and gRPC client type. ```bash dotnet run -c Release --project .\perf\benchmarkapps\GrpcClient\ -- -u http://localhost:5000 -c 10 --streams 50 -s unary -p h2c --grpcClientType grpcnetclient ``` -------------------------------- ### Run gRPC-dotnet Benchmark Server with Named Pipes Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/README.md Launches the gRPC server for benchmarking using named pipes. Specify the named pipe name for communication. ```bash dotnet run -c Release --project .\perf\benchmarkapps\GrpcAspNetCoreServer\ --protocol h2c --namedPipeName PerfPipe ``` -------------------------------- ### Build gRPC C# Components Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsWebsite/README.md Follow the provided link for instructions on building gRPC C# as a developer. This command builds the components in debug mode. ```bash python tools/run_tests/run_tests.py -l csharp -c dbg --build_only ``` -------------------------------- ### Run gRPC-dotnet Benchmark Server with TCP Sockets Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/README.md Launches the gRPC server for benchmarking using TCP sockets. Ensure the protocol is set to h2c. ```bash dotnet run -c Release --project .\perf\benchmarkapps\GrpcAspNetCoreServer\ --protocol h2c ``` -------------------------------- ### Build and Run gRPC-Web Server Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/README.md Instructions to build and run the gRPC-Web server using Docker Compose. The server will be accessible at http://localhost:8080. ```bash docker compose -f docker-compose.yml build grpcweb-server docker compose -f docker-compose.yml up grpcweb-server ``` -------------------------------- ### Populate DebugInfo with Exception on Server Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Use the `ToRpcDebugInfo()` extension method on `System.Exception` to create a `DebugInfo` message. This message is then packed into the `Details` of a `Google.Rpc.Status` object before being converted to an `RpcException`. ```C# try { // ... } catch (Exception e) { throw new Google.Rpc.Status { Code = (int)Google.Rpc.Code.Internal, Message = "Internal error", Details = { // populate debugInfo from the exception Any.Pack(e.ToRpcDebugInfo()), // Add any other messages to the details ... } }.ToRpcException(); } ``` -------------------------------- ### Configure gRPC in Program.cs Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.AspNetCore/README.md Use `AddGrpc` to enable gRPC services and `MapGrpcService` to map specific gRPC services to the routing pipeline in your ASP.NET Core application. ```csharp using GrpcGreeter.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddGrpc(); var app = builder.Build(); // Configure the HTTP request pipeline. app.MapGrpcService(); app.Run(); ``` -------------------------------- ### Generate gRPC-Web Client and Messages with protoc Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Browser/Server/wwwroot/Scripts/README.md Use this command to generate gRPC-Web JavaScript clients and messages from a .proto file. Ensure protoc and protoc-gen-grpc-web are in your PATH, and replace placeholders with your actual directory and executable paths. ```powershell protoc greet.proto --js_out=import_style=commonjs:CHANGE_TO_SCRIPTS_DIRECTORY --grpc-web_out=import_style=commonjs,mode=grpcwebtext:CHANGE_TO_SCRIPTS_DIRECTORY --plugin=protoc-gen-grpc-web=CHANGE_TO_PROTOC_GEN_GRPC_WEB_EXE_PATH ``` -------------------------------- ### Configure gRPC-Web Globally Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.AspNetCore.Web/README.md Enable gRPC-Web for all services by setting `GrpcWebOptions.DefaultEnabled` to true in `Program.cs`. This configuration should be placed before mapping gRPC services. ```csharp using GrpcGreeter.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddGrpc(); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseRouting(); app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true }); app.MapGrpcService(); app.Run(); ``` -------------------------------- ### Using Open Iconic with Foundation Classes Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Render icons using the 'fi' class, followed by the specific icon name. Include 'title' for tooltips and 'aria-hidden' for accessibility. ```html ``` -------------------------------- ### Run gRPC Tests Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md Execute tests for the gRPC project from the command line using the dotnet CLI. This command runs all tests defined in the solution. ```bash dotnet test Grpc.DotNet.slnx ``` -------------------------------- ### Enable gRPC-Web for Individual Services Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.AspNetCore.Web/README.md Enable gRPC-Web for a specific gRPC service by calling `.EnableGrpcWeb()` on the `MapGrpcService` configuration. This allows for more granular control over which services support gRPC-Web. ```csharp app.MapGrpcService().EnableGrpcWeb(); ``` -------------------------------- ### Configure gRPC-Web Channel Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client.Web/README.md Use GrpcChannel.ForAddress with a GrpcWebHandler to enable gRPC-Web communication. Ensure the Grpc.Net.Client package is version 2.29.0 or greater. ```csharp 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" }); ``` -------------------------------- ### Create gRPC Channel and Client Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/README.md Create a gRPC channel for a given address and use it to instantiate a gRPC client. Channels represent long-lived connections and can be configured with options like message size and logging. ```csharp var channel = GrpcChannel.ForAddress("https://localhost:5001"); var client = new Greet.GreeterClient(channel); ``` ```csharp var channel = GrpcChannel.ForAddress("https://localhost:5001"); var greeterClient = new Greet.GreeterClient(channel); var counterClient = new Count.CounterClient(channel); // Use clients to call gRPC services ``` -------------------------------- ### Configure gRPC NuGet Feed Source: https://github.com/grpc/grpc-dotnet/blob/master/README.md Add this repository to your NuGet configuration to access nightly builds of gRPC for ASP.NET Core. Ensure your .NET Core SDK version matches the gRPC package version to avoid incompatibilities. ```xml ``` -------------------------------- ### Run Aggregator with OpenTelemetry Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/README.md This command enables OpenTelemetry for the aggregator server, capturing tracing information. ```console dotnet run --EnableOpenTelemetry=true ``` -------------------------------- ### Create and Throw RpcException with Rich Error Details Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Demonstrates how to create and throw an RpcException containing detailed error information using Google.Rpc.Status. This is useful for server-side error handling when specific validation fails. ```C# public override Task SayHello(HelloRequest request, ServerCallContext context) { ArgumentNotNullOrEmpty(request.Name); return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); } private static void ArgumentNotNullOrEmpty(string value, [CallerArgumentExpression(nameof(value))] string? paramName = null) { if (string.IsNullOrEmpty(value)) { throw new Google.Rpc.Status { Code = (int)Code.InvalidArgument, Message = "Bad request", Details = { Any.Pack(new BadRequest { FieldViolations = { new BadRequest.Types.FieldViolation { Field = paramName, Description = "Value is null or empty" } } }) } }.ToRpcException(); } } ``` -------------------------------- ### Register gRPC Client with HttpClientFactory Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.ClientFactory/README.md Register a gRPC typed client with dependency injection using the generic AddGrpcClient extension method. Configure the service address for the client. ```csharp services.AddGrpcClient(o => { o.Address = new Uri("https://localhost:5001"); }); ``` -------------------------------- ### Including Open Iconic with Foundation Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Link to the Foundation-specific stylesheet to integrate Open Iconic with the Foundation framework. This allows usage of 'fi' classes for icons. ```html ``` -------------------------------- ### Initialize Blazor Test Helper Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsGrpcWebClient/wwwroot/index.html This code is called by Blazor once it is loaded and ready to run tests. It assigns the provided testHelper object to a global variable for later use. ```javascript var host = 'localhost'; var port = 8080; // This will be called by Blazor once it is loaded and ready to run tests window.initialTestHelper = (testHelper) => { window.testHelper = testHelper; }; ``` -------------------------------- ### Using Open Iconic Standalone Classes Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Display icons using the 'oi' class and the 'data-glyph' attribute to specify the icon. 'title' provides a tooltip, and 'aria-hidden' aids accessibility. ```html ``` -------------------------------- ### Generate PKCS12 Certificate Source: https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/Shared/Certs/README.md Use this OpenSSL command to export a PKCS12 file from a private key, certificate, and CA certificate. The generated PFX file can be used with a password for secure server authentication in testing scenarios. ```bash openssl pkcs12 -export -out server1.pfx -inkey server1.key -in server1.pem -certfile ca.pem ``` -------------------------------- ### Send Streaming Request to Greeter Service Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/wwwroot/index.html This JavaScript code sends a streaming POST request to the Greeter service. JSON is sent in the request body. It handles reading the response stream and displaying the results. Ensure the HTML elements with IDs 'nameStream', 'countStream', 'sendStream', and 'resultStream' exist. ```javascript var nameStreamInput = document.getElementById('nameStream'); var countStreamInput = document.getElementById('countStream'); var streamForm = document.getElementById('sendStream'); var resultStreamText = document.getElementById('resultStream'); streamForm.addEventListener('submit', function (event) { resultStreamText.innerHTML = ''; var url = '/v1/greeter'; var content = JSON.stringify({ name: nameStreamInput.value, count: parseInt(countStreamInput.value) }); fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: content }).then(async function (response) { var reader = response.body.getReader(); var decoder = new TextDecoder('utf-8'); var buffer = ''; var values = []; let done, value; while (!done) { ({ value, done } = await reader.read()); if (done) { displayData(resultStreamText, url, content, response, values, true); break; } buffer += decoder.decode(value, { stream: true }); var lines = buffer.split(/[ ]/); buffer = lines.pop(); values.push(...lines); displayData(resultStreamText, url, content, response, values, false); } }); event.preventDefault(); event.stopPropagation(); }, false); ``` -------------------------------- ### Make Client Streaming gRPC Call Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/README.md Initiate a client streaming gRPC call. Send messages using `RequestStream.WriteAsync()`, then call `RequestStream.CompleteAsync()` to notify the service. The response is received after completion. ```csharp var client = new Counter.CounterClient(channel); using var call = client.AccumulateCount(); for (var i = 0; i < 3; i++) { await call.RequestStream.WriteAsync(new CounterRequest { Count = 1 }); } await call.RequestStream.CompleteAsync(); var response = await call; Console.WriteLine($"Count: {response.Count}"); // Count: 3 ``` -------------------------------- ### Including Open Iconic Standalone Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Link to the default Open Iconic stylesheet for standalone usage. This enables the 'oi' class with the 'data-glyph' attribute for icon selection. ```html ``` -------------------------------- ### Run Specific Test in Blazor Source: https://github.com/grpc/grpc-dotnet/blob/master/testassets/InteropTestsGrpcWebClient/wwwroot/index.html Executes a specified test within the Blazor application using the provided host, port, mode, and test name. This function interacts with the Blazor test helper to initiate the test execution. ```javascript // Call into Blazor to run the specified test function runTest(name, mode) { var testHelper = window.testHelper; return testHelper.invokeMethodAsync('RunTestAsync', host, port, mode, name); } ``` -------------------------------- ### Make Server Streaming gRPC Call Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/README.md Initiate a server streaming gRPC call. Read messages from the response stream using `ResponseStream.MoveNext()` until it returns false, or use `ReadAllAsync()` with `await foreach` for C# 8+. ```csharp var client = new Greet.GreeterClient(channel); using var call = client.SayHellos(new HelloRequest { Name = "World" }); while (await call.ResponseStream.MoveNext()) { Console.WriteLine("Greeting: " + call.ResponseStream.Current.Message); // "Greeting: Hello World" is written multiple times } ``` ```csharp var client = new Greet.GreeterClient(channel); using var call = client.SayHellos(new HelloRequest { Name = "World" }); await foreach (var response in call.ResponseStream.ReadAllAsync()) { Console.WriteLine("Greeting: " + response.Message); // "Greeting: Hello World" is written multiple times } ``` -------------------------------- ### Make Unary gRPC Call Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.Client/README.md Initiate a unary gRPC call by invoking an asynchronous method on the client. The client handles serialization and addressing. Use the asynchronous method for non-blocking operations. ```csharp var client = new Greet.GreeterClient(channel); var response = await client.SayHelloAsync(new HelloRequest { Name = "World" }); Console.WriteLine("Greeting: " + response.Message); // Greeting: Hello World ``` -------------------------------- ### Including Open Iconic with Bootstrap Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Link to the Bootstrap-specific stylesheet to use Open Iconic with Bootstrap framework classes. This enables the 'oi' class for icon display. ```html ``` -------------------------------- ### Helper Functions for HTTP Requests Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/wwwroot/index.html Contains utility functions for displaying data and escaping HTML. The `displayData` function formats the request and response, while `htmlEscape` and `getReasonPhrase` handle specific formatting and status code translations. ```javascript function displayData(text, url, content, response, values, done) { text.innerHTML = `
Request

POST ${url}

${htmlEscape(content)}

Response

HTTP/1.1 ${response.status} ${getReasonPhrase(response.status)}

${values.map(v => htmlEscape(v) + "
").join("")}

`; if (done) { text.innerHTML += `
Result
    ${values.map(v => "
  • " + JSON.parse(v).message + "
  • ").join("")}
`; } } ``` ```javascript function htmlEscape(str) { return String(str) .replace(/&/g, '&') .replace(/'/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } ``` ```javascript function getReasonPhrase(statusCode) { switch (statusCode) { case (200): return "OK"; case (201): return "Created"; case (202): return "Accepted"; case (203): return "Non Authoritative Information"; case (204): return "No Content"; case (205): return "Reset Content"; case (206): return "Partial Content"; case (207): return "Partial Update OK"; case (300): return "Mutliple Choices"; case (301): return "Moved Permanently"; case (302): return "Moved Temporarily"; case (303): return "See Other"; case (304): return "Not Modified"; case (305): return "Use Proxy"; case (307): return "Temporary Redirect"; case (400): return "Bad Request"; case (401): return "Unauthorized"; case (402): return "Payment Required"; case (403): return "Forbidden"; case (404): return "Not Found"; case (405): return "Method Not Allowed"; case (406): return "Not Acceptable"; case (407): return "Proxy Authentication Required"; case (408): return "Request Timeout"; case (409): return "Conflict"; case (410): return "Gone"; case (411): return "Length Required"; case (412): return "Precondition Failed"; case (413): return "Request Entity Too Large"; case (414) ``` -------------------------------- ### Displaying Open Iconic SVGs Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Use this method to display individual Open Iconic SVGs like any other image. Remember to include an alt attribute for accessibility. ```html icon name ``` -------------------------------- ### Using Open Iconic with Bootstrap Classes Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Display icons using the 'oi' class and specify the icon name. The 'title' attribute provides a tooltip, and 'aria-hidden' improves accessibility. ```html ``` -------------------------------- ### Protobuf Service Definition for Streaming Responses with Status Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Defines a gRPC service with a streaming RPC that can return either widget details or an error status in its responses. This allows clients to handle errors without the stream terminating. ```protobuf service WidgetLookupProvider { rpc streamingLookup(stream WidgetReq) returns (stream WidgetRsp) {} } message WidgetReq { string widget_name = 1; } message WidgetRsp { oneof message{ // details when ok string widget_details = 1; // or error details google.rpc.Status status = 2; } } ``` -------------------------------- ### Using Open Iconic SVG Sprite Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Incorporate icons from the SVG sprite for efficient loading. Add a general class to the SVG and a specific class to the use tag for styling. ```html ``` -------------------------------- ### Inject and Consume gRPC Client in ASP.NET Core Service Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.Net.ClientFactory/README.md Inject a gRPC typed client into an ASP.NET Core service (e.g., AggregatorService) via its constructor. The client is registered as transient with dependency injection. ```csharp public class AggregatorService : Aggregator.AggregatorBase { private readonly Greeter.GreeterClient _client; public AggregatorService(Greeter.GreeterClient client) { _client = client; } public override async Task SayHellos(HelloRequest request, IServerStreamWriter responseStream, ServerCallContext context) { // Forward the call on to the greeter service using (var call = _client.SayHellos(request)) { await foreach (var response in call.ResponseStream.ReadAllAsync()) { await responseStream.WriteAsync(response); } } } } ``` -------------------------------- ### Sizing Icons with CSS Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Blazor/Client/wwwroot/css/open-iconic/README.md Set equal width and height on the SVG tag to control icon size. This CSS applies to all icons using the 'icon' class. ```css .icon { width: 16px; height: 16px; } ``` -------------------------------- ### Iterate and Unpack Detail Messages from RpcException on Client Source: https://github.com/grpc/grpc-dotnet/blob/master/src/Grpc.StatusProto/README.md Use `UnpackDetailMessages()` to iterate through all messages within the `Details` of a `Google.Rpc.Status` object retrieved from an `RpcException`. This method allows for type-safe handling of different detail message types. ```C# void PrintStatusDetails(RpcException ex) { // Get the status from the RpcException Google.Rpc.Status? rpcStatus = ex.GetRpcStatus(); // Extension method if (rpcStatus != null) { // Decode each message item in the details in turn foreach (var msg in rpcStatus.UnpackDetailMessages()) { switch (msg) { case ErrorInfo errorInfo: Console.WriteLine($"ErrorInfo: Reason: {errorInfo.Reason}, Domain: {errorInfo.Domain}"); foreach (var md in errorInfo.Metadata) { Console.WriteLine($"\tKey: {md.Key}, Value: {md.Value}"); } break; case BadRequest badRequest: Console.WriteLine("BadRequest:"); foreach (BadRequest.Types.FieldViolation fv in badRequest.FieldViolations) { Console.WriteLine($"\tField: {fv.Field}, Description: {fv.Description}"); } break; // Other cases handled here ... } } } } ``` -------------------------------- ### HTTP Status Code to Reason Phrase Mapping Source: https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/wwwroot/index.html Maps common HTTP status codes to their corresponding reason phrases. Useful for handling HTTP responses in a gRPC context. ```csharp case (400): return "Bad Request"; case (401): return "Unauthorized"; case (402): return "Payment Required"; case (403): return "Forbidden"; case (404): return "Not Found"; case (405): return "Method Not Allowed"; case (406): return "Not Acceptable"; case (407): return "Proxy Authentication Required"; case (408): return "Request Timeout"; case (409): return "Conflict"; case (410): return "Gone"; case (411): return "Length Required"; case (412): return "Precondition Failed"; case (413): return "Request-Entity Too Large"; case (414): return "Request-URI Too Long"; case (415): return "Unsupported Media Type"; case (416): return "Requested Range Not Satisfiable"; case (417): return "Expectation Failed"; case (418): return "Reauthentication Required"; case (419): return "Proxy Reauthentication Required"; case (422): return "Unprocessable Entity"; case (423): return "Locked"; case (424): return "Failed Dependency"; case (500): return "Server Error"; case (501): return "Not Implemented"; case (502): return "Bad Gateway"; case (503): return "Service Unavailable"; case (504): return "Gateway Timeout"; case (505): return "HTTP Version Not Supported"; case (507): return "Insufficient Storage"; default: return ""; } ```