SHARE:

gRPC & ASP.NET Core 3.1: How to create a gRPC-web client ? Examples with Angular 8 and HttpClient

Create gRPC-web app with Angular 8 on Windows

I chose to make a demo with Angular 8 (it could have been React or Vue) because Angular 8 language is Typescript and I recommend to work with Typescript for Front-end development.

Improbable gRPC-web library is an implementation for Typescript (not only) and I will use this one to make a SPA app with Angular 8.

Install protoc

First we need to install the protobuf compiler (protoc) here: https://github.com/protocolbuffers/protobuf/releases and choose the Windows that suits to your OS:

Don’t select the Javascript version, because we are using TypeScript

Then I strongly recommend to install protoc in your PATH

Install required node modules

Because protoc doesn’t support TypeScript we need a plugin that makes protoc able to create TypeScript services and client from a .proto file and this plugin is ts-protoc-gen:

npm install --save-dev

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

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

Generate services, messages and client

Let’s use this time a .proto file that describe a country service with a method named “GetAll”

Let’s generate now in TypeScript the service, message and the client, this command is executed in src root folder of of the Angular 8 app:

protoc --plugin=protoc-gen-ts="{ABSOLUTEPATH}\node_modules\.bin\protoc-gen-ts.cmd" 
       --js_out="import_style=commonjs,binary:src/app/generated" 
       --ts_out="service=grpc-web:src/app/generated" src/app/protos/{YOURPROTOFILENAME}.proto

On Windows your have to use the absolute path to ts-protoc-gen node module, and use .cmd extension

You’ll probably have to fix in your generated services file the path of your dependency, extra folder levels have been added in my case (maybe a protoc bug). In your yourprotoname_pb_service.d.ts and yourprotoname_pb_service.js remove extra folders level like this:

import * as src_app_protos_yourprotoname_pb from "../generated/yourprotoname_pb";
var src_app_protos_yourprotoname_pb = require("../generated/yourprotoname_pb");

After these steps your folder should contains 4 files, 2 in javascript (services + client file and messages (entities) file) + 2 in TypeScript (definition files)

Consume a service, example of an unary call:

Implementing a gRPC-web service is a bit more complex than a simple request from REST API, the country sample with the GetAll method looks like this:

var result = message.toObject() as CountriesReply.AsObject; is the process of deserialization, it’s a bit weird the first time, but once you did it once it’s easy to understand.

Demo

You can try my demo here (hosted in a static website, don’t forget to add index.html as entry point): https://anthonygiretti.blob.core.windows.net/grpcwebdemo/index.html

Here is how the response looks like in Chrome (gRPC-web is human readable un like gRPC):

The complete source code can be found here: https://github.com/AnthonyGiretti/angular8-grpc-aspnetcore3-1-demo 🙂

Create gRPC-web client in a console app

We have already seen how to create a gRPC client in an app console, but gRPC-web client is different. In this scenario we need a new package to be able to write a gRPC-web client in .NET with HttpClient.

Reminder: gRPC & ASP.NET Core 3.1: How to create a gRPC client ?

In a gRPC-web client scenario you need to add another package (Grpc.Net.Client.Web), for now it’s in preview:

PM> Install-Package Grpc.Net.Client.Web -Version 2.28.0-pre2

Note this package targets .NETStandard 2.1, in consequence you can only use it in .NET Core 3+ project and obviously .NETStandard 2.1 librairies because features that are required (trailers) were added in .NETStandard 2.1.

Here is how your .csproj should look:

The Grpc.Net.Client.Web client looks like this:

The client requires a specific gRPC-web handler (GrpcWebHandler), that needs in parameters a new HttpClientHandler to be instanciated, the gRPC-web mode and optionally the HttpVersion which defaults HTTP/2 (HttpVersion.Version20) if it’s not set.

Like a gRPC client, as long as soon as an exception is raised you have to catch it with RpcException.

Conclusion

This demo demonstrates how we can consume gRPC-web service with recent SPAs (+ TypeScript) technologies and how to consume it from a .NET Client.

You can definitely make it works also on pure Javascript application if you download the dedicated protoc tool.

Even if I built a demo with a console app for a .NET Client, it’s also compatible with Blazor, ASP.NET Core 3 app (back end to back end) and even Xamarin and the code is exactly the same.

In the next article we will see how to handle exceptions server side. See you soon again ! 🙂

Written by

anthonygiretti

Anthony is a specialist in Web technologies (14 years of experience), in particular Microsoft .NET and learns the Cloud Azure platform. He has received twice the Microsoft MVP award and he is also certified Microsoft MCSD and Azure Fundamentals.
%d bloggers like this: