News
.NET 5 Blazor Powers 'Rock, Paper, Scissors, Lizard, Spock' Game
A Microsoft project demonstrates a .NET 5 Blazor upgrade by powering a digital variation of the old Rock, Paper, Scissors hand game.
That web game is called "Rock, Paper, Scissors, Lizard, Spock (RPSLS), based on a more difficult version of the hand game that was invented by Sam Kass and Karen Bryla, using more "weapons" ("Spock vaporizes rock").
Microsoft had originally created the project using the server-side component of Blazor, appropriately called Blazor Server. Its focus wasn't on Blazor so much as Azure services that serve to demonstrate the scalability of the company's cloud platform.
Microsoft's Isaac Levin explained:
RPSLS is a microservice architecture solution built inside of Azure Kubernetes Service. In the game, you can play against a friend using a unique URL, or you can play against a bot. What is a bot? A bot is a "mascot" representation of 5 of the many languages you can build apps with inside Azure. The ones we picked were: C#, Java, NodeJs, Python and PHP. When you play against a bot, you are actually playing against a microservice running in that particular language. For instance, when you choose C# (my favorite language) as an opponent, there is a service running in .NET that predicts my next move. Once the service "guesses my move", it attempts to pick a move to beat me. That prediction runs in .NET. Along with the .NET bot microservice running in .NET, the web UI also runs in .NET, .NET Core 3.1 Blazor Server to be exact.
With the advent of .NET 5, which was meant to unify disparate .NET tooling components and frameworks into one umbrella offering, the game was updated. In the update, the team decided to switch from Blazor Server to Blazor WebAssembly, the client-side component. It went GA with .NET 5 last November, lagging behind Blazor Server.
Microsoft documentation explains the differences between the two components.
The primary Blazor hosting model is running client-side in the browser on WebAssembly. The Blazor app, its dependencies, and the .NET runtime are downloaded to the browser. The app is executed directly on the browser UI thread. UI updates and event handling occur within the same process. The app's assets are deployed as static files to a web server or service capable of serving static content to clients.
With the Blazor Server hosting model, the app is executed on the server from within an ASP.NET Core app. UI updates, event handling, and JavaScript calls are handled over a SignalR connection.
The updated .NET 5 project documented the process of moving an existing .NET Core application leveraging Blazor Server to .NET 5 using Blazor WebAssembly.
In the port from Blazor Server to Blazor WebAssembly, the team accomplished the following, according to a March 17 blog post authored by Levin.
- A new project was created using the Blazor WebAssembly hosted template. This creates 3 projects; a
Client
project for the UI, a backend Server
project for the UI to call, and a Shared
project which will hold shared models and services.
- Move the file content from the Blazor Server
_Host.cshtml
page content to the index.html
in the static folder of the newly created project and replace the existing _framework/blazor.server.js with the new _framework/blazor.client.js
reference in that file. The newly referenced .js file will be the new entry point of the SPA.
- Migrate all .razor files in the old project to the new Client project
- Using the Options pattern in .NET 5 in the Client project to retrieve any configuration settings from the Server project using modern retrieval methods (browser fetch API)
- Configure the Client project to use JSRuntime to initialize Google Analytics with the Api key fetched from the backend (the Blazor Analytics NuGet package allowed us to do it out of the box)
- Implement a custom AuthenticationState provider that checks if the user is logged in before calling the server (the user can either log with Twitter, or provide a string that represents their username
- gRPC calls made from Blazor components to the Game API are now executed from Client project and, as the game API is not exposed to internet, we created a game a factory service to forward the requests to the backend Server API.
Levin cautioned that the above is a simplification of the actual work involved, which he described as both "not very complicated" as well as "not trivial."
"Overall, the experience was great! Developing multiple layers of the app all in the same language made it feel like you aren't building a client side app, but since the Client project gets compiled down to native WebAssembly, you are," he said. "One of the key points is that our application doesn't require persistence, so we were able to migrate to Blazor WebAssembly without big changes in the components."
He pointed to the GitHub repo for more information -- or just to play the game, "for no other reason other than it is fun."
You can play the game on the web here.
About the Author
David Ramel is an editor and writer at Converge 360.