Hi All! Today we’re going to talk about how to consume a gRPC service from a Blazor client. And we’re going to do it with Dungeons & Dragons!
People who know me, know that deep down, I’m a big nerd. I started playing D&D when I was a freshman in college and kept going for years. Eventually, I began writing my own campaigns, holding sessions as Dungeon Master, and even participating in competitions. And winning.
I play Baldur’s Gate 2 at least once a year. Each time with a different class/race. Oh boy, that game is massive!
The last game I bought on Steam? Icewind Dale. Of course, I played it in the past but never had the pleasure of “owning” it.
So what does all of this with Blazor and gRPC? Well, a few days ago I was looking for a fun way to study them both. And I thought: is there anything out in the interwebz that I can leverage?
And the answer, of course, was yes: the D&D 5e REST API! It’s free and doesn’t require any auth so it’s a perfect way to feed some data in our app.
My goal? Well as I said, I just wanted to play with Blazor and gRPC. And have some fun in the meantime.
So I wrote a simple Blazor webassembly gRPC client to display an archive of D&D classes. You can click on a row and get redirected to a detail page. Easy peasy.
The data is coming from a separate application, exposing a gRPC service. This server is basically just a simple proxy over the D&D REST API. I deliberately decided to not add any caching or other fancy things, just to focus on the transport.
Now, due to browser limitations, we can’t really use gRPC here, but we can rely on gRPC-web instead. Let me quote James Newton-King:
It is impossible to implement the gRPC HTTP/2 spec in the browser because there is no browser API with enough fine-grained control over HTTP requests. gRPC-Web solves this problem by being compatible with HTTP/1.1 and HTTP/2.
For those interested, the full article is here.
As usual, the code is available on GitHub, help yourself.
Let’s explore the client today. The first step is to add our .proto file, defining the layout of our messages:
Not much to say here. We have two methods, one returning all the available classes (and taking no parameter: thank you google.protobuf.Empty ). The other one instead returns the class details given the id.
Notice how I’ve leveraged the repeated keyword to define arrays of complex objects.
Now, an extremely important step is to make sure our .proto definition is properly referenced in our .csproj file:
That GrpcServices=”Client” will basically tell Visual Studio to generate the client proxy classes for us. Quite handy indeed.
Now we have to plug the client in our DI container in our Program.cs:
As you can see, I’m using GrpcWebMode.GrpcWeb here. I’m not doing any streaming, just unary calls so no need to use GrpcWebMode.GrpcWebText. This gives me the benefit of smaller messages:
For those interested, here’s a nice article explaining the difference between unary and streamed calls.
Now the last step: let’s call our service! That’s actually the easy part:
As you can see, the Client is injected and invoked during page initialization. Stop. No strings attached. Told you t’was easy.
In another article we’ll take a look at our server instead. Thanks for reading!