A Complete Guide to gRPC-Web with Angular and .NET (2024)

A Complete Guide to gRPC-Web with Angular and.NET (1)

·

Follow

Published in

ITNEXT

·

10 min read

·

May 19, 2022

--

A Complete Guide to gRPC-Web with Angular and.NET (3)

In this post, we’ll create a gRPC demo containing a server that uses a gateway and two clients(.NET, Angular). We will also go through some common problems that you might face when building gRPC servers and clients.

What is gRPC?

If you’re looking for a way to improve your application’s performance, you may want to consider using gRPC. gRPC is a high-performance, open-source universal RPC framework that can run in any environment. gRPC is based on the concept of a remote procedure call (RPC). An RPC is a method of communication between two systems that allows them to exchange information. It’s also language-agnostic, so you can use it with any programming language, and makes it easy to build connected systems.

GRPC uses HTTP/2 as its transport layer, which provides several benefits over traditional HTTP/1.1. HTTP/2 is a binary protocol that multiplexes requests and responses over a single connection and uses header compression to reduce overhead. This makes it much more efficient than HTTP/1.1 and allows for lower latency and higher throughput.

In addition, GRPC uses Protocol Buffers as its interface description language. This allows for strong type checking and efficient serialization of data. It also makes it easy to evolve the API over time, without breaking backward compatibility.

There are many benefits of using Grpc, but some of the most notable ones include:

Lightweight messages. Depending on the type of call, gRPC-specific messages can be up to 30 percent smaller in size than JSON messages.

High performance. By different evaluations, gRPC is 5, 7, and even 8 times faster than REST+JSON communication.

Built-in code generation. gRPC has automated code generation in different programming languages including Java, C++, Python, Go, Dart, Objective-C, Ruby, and more.”

More connection options. While REST focuses on request-response architecture, gRPC provides support for data streaming with event-driven architectures: server-side streaming, client-side streaming, and bidirectional streaming

Source: https://www.altexsoft.com/blog/what-is-grpc/

We will build a gRPC server with .NET and two clients (Angular, .NET) in this article.

Because many browsers’ clients don’t support gRPC we will configure our server and clients for gRPC-web which is different than gRPC. It exists solely in a browser and acts as a translation layer between gRPC and your application in a browser. The “web” client in gRPC-Web receives requests over HTTP 1.1 or HTTP/2 and then sends the requests through a proxy. You can find more details in this post.

Building gRPC server with .NET

Firstly, let’s create a new .NET application with the code written below.

dotnet new web -o gRPC.Web.Server

Then, we need to install Grpc.AspNetCore and Grpc.AspNetCore packages to our project to be able to use Grpc features.

dotnet add gRPC.Web.Server.csproj package Grpc.AspNetCore
dotnet add gRPC.Web.Server.csproj package Grpc.AspNetCore.Web

Creating Proto File

As we know, gRPC uses .proto files so we will need to define our protobuf file that’ll be used by the client and the server-side. Let’s create a directory named “Protos” and just create a simple protobuf file named “stream.proto” there, like this:

syntax = "proto3";

service StreamService {
rpc FetchResponse (Request) returns (stream Response) {}
}

message Request {
int32 id = 1;
}

message Response {
string result = 1;
}

If you want to learn more about proto files you can visit this source.

After creating a proto file we need to define it into our .csproj file to will be able to use auto-generated codes that we can inherit and override.

<ItemGroup> <Protobuf Include="Protos\stream.proto" GrpcServices="Server" /></ItemGroup>

Note: By default, a <Protobuf> reference generates a concrete client and a service base class. The reference element's GrpcServices attribute can be used to limit C# asset generation. Valid GrpcServices options are: Both(default when not present), Server, Client and None.

After executing the dotnet build command we should see generated classes under obj/Debug/net* folder as below.

A Complete Guide to gRPC-Web with Angular and.NET (4)

Implementing Generated Class

Let’s create StreamImplService which implements our service method. FetchResponse is a server-side streaming RPC, so we need to send back multiple Response protocol buffers to our client.

using Grpc.Core;

public class StreamImplService: StreamService.StreamServiceBase {

private readonly List<string> _messages = new List<string>()
{
"Hello",
"World",
"!"
};

public override async Task FetchResponse(
Request request,
IServerStreamWriter<Response> responseStream,
ServerCallContext context)
{
while (!context.CancellationToken.IsCancellationRequested)
{
foreach (var message in _messages)
{
await responseStream.WriteAsync(new Response()
{
Result = message
});

Thread.Sleep(750);
}
}
}
}

As you can see, instead of returning a simple response we write responses to an asynchronous stream IServerStreamWriter using the async method WriteAsync while cancellation token is not requested. Our Request model contains an Id property but I won’t do anything with that value at this moment.

We need to configure Program.cs (Startup.cs for previous versions) as below.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();app.UseGrpcWeb();

app.MapGrpcService<StreamImplService>().EnableGrpcWeb();

app.Run();

For previous versions:

services.AddGrpc();app.UseGrpcWeb();app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<StreamImplService>().EnableGrpcWeb(); });

According to Microsoft gRPC template uses TLS by default and Kestrel doesn’t support HTTP/2 with TLS on macOS systems as a result of that we can say macOS doesn’t support ASP.NET Core gRPC with TLS and requires additional config for using HTTP2. Note: This configuration is only for gRPC if you want to use gRPC-web as in this post there is no need for doing this.

using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(7264, o => o.Protocols = HttpProtocols.Http2);
});

var app = builder.Build();

app.UseGrpcWeb();

app.MapGrpcService<StreamImplService>().EnableGrpcWeb();

app.Run();

💡 Don’t do this in production! This is intended for local development purposes only.

We also need to configure the SSL trust:

dotnet dev-certs https --trust

And finally, we are ready for requests.

Calling gRPC APIs with Kreya

Since we cannot send requests to gRPC APIs with Postman or other traditional approaches you might be looking for a tool that can help you with testing/debugging like Postman, In that case, Kreya might be a good choice.

Firstly you need to download Kreya from the URL written below.
https://kreya.app/downloads/

After installation click Create Project Button

A Complete Guide to gRPC-Web with Angular and.NET (5)

Then select a location for project files and fill in other inputs as you wish.

A Complete Guide to gRPC-Web with Angular and.NET (6)

Click Project/Importers set type as gRPC proto files and add our Protos folder inside the .NET project as a proto directory.

A Complete Guide to gRPC-Web with Angular and.NET (7)

You can set the endpoint from the Directory Settings section. If you want to use gRPC you should set the HTTP port that was configured for HTTP2 support, if you want to use gRPC-Web you can set both HTTP and HTTPS ports on Mac devices otherwise you should set the project’s HTTPS port.

A Complete Guide to gRPC-Web with Angular and.NET (8)
A Complete Guide to gRPC-Web with Angular and.NET (9)

Then you can send requests by clicking on the FetchReponse label which comes from our proto file and may be different depending on your proto file.

As you can see, the responses will come until the cancellation.

A Complete Guide to gRPC-Web with Angular and.NET (10)

If you don’t like Kreya, you can take look at gRPCurl.

Building gateway for gRPC-Web with YARP

Another challenge we will face is that if you want to use gRPC-Web with a gateway or if you want to use gRPC inside your project that already uses a gateway you should know that Ocelot does not support gRPC for now. Using YARP developed by Microsoft will be a good choice.

Let’s begin with creating a new project and installing Yarp.ReverseProxy with the commands below.

dotnet new web -o gRPC.Web.Gateway
dotnet add gRPC.Web.Gateway.csproj package Yarp.ReverseProxy

YARP is implemented as a .NET component, and so the majority of the sample code is in Program.cs (Startup.cs for previous versions).

var builder = WebApplication.CreateBuilder(args);// Add the reverse proxy to capability to the server
var proxyBuilder = builder.Services.AddReverseProxy();
// Initialize the reverse proxy from the "ReverseProxy" section of configuration
proxyBuilder.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();// Enable endpoint routing, required for the reverse proxy
app.UseRouting();
// Register the reverse proxy routes
app.MapReverseProxy();
app.Run();

Then, the appsettings.json file should be like the below.

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ReverseProxy": {
"routes": {
"grpc-web-service": {
"clusterId": "grpc-web-service",
"match": {
"path": "grpc/grpc-web-service/{**catch-all}"
},
"transforms": [
{
"pathPattern": "{**catch-all}"
},
{ "RequestHeadersCopy": "true" },
{ "RequestHeaderOriginalHost": "true" }
]
}
},
"clusters": {
"grpc-web-service": {
"destinations": {
"destination1": {
"address": "http://localhost:5019"
}
}
}
}
}
}

If you want to deep dive into YARP and learn advanced/detailed usages you can visit this article.

If you want to see an example config for gRPC with HTTP2 visit this article.

You should be able to send requests to our gRPC service with the gateway endpoint at this phase.

A Complete Guide to gRPC-Web with Angular and.NET (11)

Building .NET gRPC-Web Client

Let’s create another project as our gRPC client with the command written below.

dotnet new console -o gRPC.Console.Client

Then we should create a folder that contains our proto file and move the proto file into it.

We are dependent on Google.Protobuf, Grpc.Net.Client, Grpc.Net.Client.Web, and Grpc.Tools packages for building a client with .NET.

dotnet add gRPC.Console.Client.csproj package Google.Protobuf
dotnet add gRPC.Console.Client.csproj package Grpc.Tools
dotnet add gRPC.Console.Client.csproj package Grpc.Net.Client
dotnet add gRPC.Console.Client.csproj package Grpc.Net.Client.Web

After installing these packages, we need to define the proto file into our .csproj file to will be able to use auto-generated codes. This configuration is almost the same as our server but we will set the “GrpcServices” value as “Client” instead of “Server” this time.

<ItemGroup>
<Protobuf Include="Protos\stream.proto" GrpcServices="Client" />
</ItemGroup>

The path component of a gRPC channel’s address is ignored when making gRPC calls. For example, GrpcChannel.ForAddress("https://localhost:5001/ignored_path") won't use ignored_path when routing gRPC calls for the service.

The address path is ignored because gRPC has a standardized, prescriptive address structure. A gRPC address combines the package, service and method names: https://localhost:5001/PackageName.ServiceName/MethodName.

There are some scenarios when an app needs to include a path with gRPC calls. For example, when an ASP.NET Core gRPC app is hosted in an IIS directory and the directory needs to be included in the request. When a path is required, it can be added to the gRPC call using the custom SubdirectoryHandler

Source: https://docs.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-6.0#calling-grpc-services-hosted-in-a-sub-directory

According to Microsoft If you want to use a gateway or another prefix for gRPC calls we need to create a SubDirectoryHandler as specified below.

namespace gRPC.Console.Client.Handlers
{
/// <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);
}
}
}

The final structure should be as below.

A Complete Guide to gRPC-Web with Angular and.NET (12)

As the last step, we should write our logic into Program.cs as below.

A Complete Guide to gRPC-Web with Angular and.NET (13)

Building Angular gRPC-Web Client

We must install protoc which is a protocol compiler and helps us with creating auto-generated files from .proto files as the first step.

This article was written using v3.19.4 of protobuf.

Follow instructions from the URL below for installing on Windows devices.
https://www.geeksforgeeks.org/how-to-install-protocol-buffers-on-windows/

Don’t select the Javascript version, because we will use TypeScript.

For Mac devices:

brew install protobuf

Let’s create an angular project with the command below.

ng new gRPC.Angular.Client --routing=false --style=scss

Because protoc doesn’t support TypeScript we need to add the ts-protoc-gen plugin to our project.

npm install --save ts-protoc-gen

We need also to install Improbable gRPC-web library and google-protobuf package (+ its types @types/google-protobuf):

npm install --save google-protobufnpm install --save-dev @types/google-protobufnpm install --save @improbable-eng/grpc-web

Then, we should create a directory that contains our proto files. I have created a directory named “protos” and copied stream.proto file into there.

A Complete Guide to gRPC-Web with Angular and.NET (14)

Let’s change our directory to “protos” folder and create auto-generated files such as service and client with protoc.

protoc --plugin=protoc-gen-ts="../../../node_modules/.bin/protoc-gen-ts" --js_out="import_style=commonjs,binary:../generated" --ts_out="service=grpc-web:../generated" stream.proto

For Windows devices, protoc-gen-ts path should be an absolute path, and instead of protoc-gen-ts you should use protoc-gen-ts.cmd.

protoc --plugin=protoc-gen-ts="{ABSOLUTEPATH}\node_modules\.bin\protoc-gen-ts.cmd" --js_out="import_style=commonjs,binary:{OUTPUTPATH}" --ts_out="service=grpc-web:{OUTPUTPATH}" {PROTO_FILE_PATH]

We should see 4 generated files after the execution of that command above.

A Complete Guide to gRPC-Web with Angular and.NET (15)

Now, let’s implement grpc-web into app.component.ts.

Do not forget to add a cors policy that allows 4200 port to the gRPC.Web.Server project.

A Complete Guide to gRPC-Web with Angular and.NET (16)
A Complete Guide to gRPC-Web with Angular and.NET (17)

Adding JWT authentication to server and clients

You may need to use JWT authentication with your grpc applications that can be easily implemented. All you need is to add the [Authorize] attribute on the server-side.

Then, you can add your token from Metadata section in Kreya.

A Complete Guide to gRPC-Web with Angular and.NET (18)

Adding your token into the metadata section will be enough for Angular.

.NET Client:

GitHub URL: https://github.com/edisnezir/grpc-demo

About gRPC

gRPC is a high-performance, open-source universal RPC (Remote Procedure Call) framework that can run in any environment. It is based on the concept of a remote procedure call, allowing communication between two systems to exchange information. gRPC is language-agnostic, making it compatible with any programming language, and it facilitates the building of connected systems. It uses HTTP/2 as its transport layer, providing several benefits over traditional HTTP/1.1. Additionally, gRPC uses Protocol Buffers as its interface description language, allowing for strong type checking and efficient serialization of data. Some of its notable benefits include lightweight messages, high performance, and built-in code generation in various programming languages [[SOURCE 1]].

Building a gRPC Server with .NET

To build a gRPC server with .NET, you would first create a new .NET application and install the necessary packages, such as Grpc.AspNetCore and Grpc.AspNetCore.Web. Then, you would define a protobuf file, implement the generated class, and configure the program accordingly. It's important to note that specific configurations may be required for different environments, such as macOS systems. Additionally, tools like Kreya can be used for testing and debugging gRPC APIs [[SOURCE 1]].

Building a Gateway for gRPC-Web with YARP

If you want to use gRPC-Web with a gateway or within a project that already uses a gateway, YARP (Yet Another Reverse Proxy) developed by Microsoft can be a suitable choice. To implement YARP, you would create a new project, install Yarp.ReverseProxy, and configure the reverse proxy routes in the appsettings.json file. This allows you to send requests to the gRPC service with the gateway endpoint [[SOURCE 1]].

Building .NET gRPC-Web Client

To create a gRPC-Web client with .NET, you would first create a new project and install the required packages, such as Google.Protobuf, Grpc.Net.Client, Grpc.Net.Client.Web, and Grpc.Tools. After defining the protobuf file in the .csproj file, you can implement the gRPC-Web logic in the client's Program.cs. Additionally, considerations for addressing specific scenarios, such as including a path with gRPC calls, may be necessary [[SOURCE 1]].

Building Angular gRPC-Web Client

To create an Angular gRPC-Web client, you would need to install protoc, a protocol compiler, and add the ts-protoc-gen plugin to the project. After creating the necessary directory for the proto files and generating the auto-generated files, you can implement gRPC-Web into the app.component.ts. It's also important to consider adding JWT authentication to the server and clients, which can be easily implemented by adding the [Authorize] attribute on the server-side and including the token from the Metadata section in the client applications [[SOURCE 1]].

This comprehensive overview of gRPC and its implementation with .NET, Angular, and YARP demonstrates a deep understanding of the topic and provides practical insights into building gRPC servers and clients.

A Complete Guide to gRPC-Web with Angular and .NET (2024)
Top Articles
Latest Posts
Article information

Author: Reed Wilderman

Last Updated:

Views: 6629

Rating: 4.1 / 5 (52 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Reed Wilderman

Birthday: 1992-06-14

Address: 998 Estell Village, Lake Oscarberg, SD 48713-6877

Phone: +21813267449721

Job: Technology Engineer

Hobby: Swimming, Do it yourself, Beekeeping, Lapidary, Cosplaying, Hiking, Graffiti

Introduction: My name is Reed Wilderman, I am a faithful, bright, lucky, adventurous, lively, rich, vast person who loves writing and wants to share my knowledge and understanding with you.