Blazor Learnings - Realtime planning poker with Blazor and SignalR
Overview
I took some time out over the past weekend to dive into a bit of Blazor Web Assembly development. These are my learnings and takeaways from the experience.
The App
Most people will already be familiar with planning poker, at a high level I wanted to support the following features
- Realtime remote collaboration
- Create new game or join existing game in progress
- Votes remain hidden until everyone has voted
- Reset the game for all participants
if you’d like to jump into the source - you can find that Here
Learnings
How easy is it to get started?
This really couldn’t have been any easier, assuming you already have the latest version of .NET Core, open your favourite terminal and run
|
|
The --hosted true
paramater indicates that you would like a separate ASP.NET Core host for the Blazor WebAssembly app
The result will be a nicely separated project structure with the server, client and shared components
And, if you hit run, you’ll get the Blazer hello world application
SignalR configuration
The SignalR package is included in the server project by default. To get SignalR up and running, all you need is a hub, and some extra configuration sauce.
Example Hub
|
|
In the Startup.cs
file, include the following highlighted changes
|
|
|
|
Besides adding your specific implementation for your Hub
this is all that was needed to get SignalR up and running.
The full implementation for my hub is available here
Hubs are transient:
- Don’t store state in a property on the hub class. Every hub method call is executed on a new hub instance.
- Use
await
when calling asynchronous methods that depend on the hub staying alive. For example, a method such asClients.All.SendAsync(...)
can fail if it’s called withoutawait
and the hub method completes beforeSendAsync
finishes.
Component Composition
Using the default approach, components are composed of both markup and C# code.
MyCoolThing.razor
|
|
To use this component from within another is simply a matter of referencing the component name in your markup.
|
|
Code Behind
At this point you might be thinking the same as I was - “Yuk, I don’t like having all my markup and c# code mixed together like this”.
So, does Blazor support a sort of Code Behind concept?
Yes, yes it does!
To do this you need to use partial
classes - Microsoft has some helpful documentation on the subject
Component Events
How can child components communicate events to a parent component?
This one turned out to be super simple too.
From with the child component, expose an EventCallback
parameter
|
|
Then wherever you use the component, just wire up a handler method
|
|
Blazor Dependency Injection
Registering services with Blazor WASM is very similar to registering services with any .NET Core application
|
|
Scoped
-registered services behave like Singleton
services.Then, within the Blazor component itself, simply include the @inject
Razor directive
|
|
Debugging
The debug configuration is all handled by the Dotnet new template, but it’s helpful to know where this configuration lives.
If you have a look at the launchSettings.json
file for the client app, you will see the following lines. (highlighted)
In case you’re wondering, wsProtocol
means WebSockets protocol
|
|
Debugging requires either of the following browsers.
- Google Chrome (version 70 or later) (default)
- Microsoft Edge (version 80 or later)
It most certainly doesn’t work with FireFox - this one caught me out for a while
State Management
A Blazor application is largely composed of a bunch of Blazor components, many of those nested within each other.
How do we maintain state across various components?
As far as I can tell there are essentially three options.
- Explicitly expose a paramater in each component, and manually plumb the data.
- Use cascading parameters - In this case, Blazor automatically exposes the data to sub-components automatically.
- Use dependency injection to create something to manage state for you.
In the case of this app, I went with option 3.
The trick is to create some kind of state manager service, and register that with the container as a singleton, then just inject it whereever you need it.
Though, I can’t say I really put all that much thought into the pro’s and con’s for each approach.
Wiring up SignalR
To get SignalR working with your app, you’ll first need to add the Microsoft.AspNetCore.SignalR.Client
Nuget package to your client.
Then, within the code section of your component, initialise a new hub, and subscribe to the relevant events.
|
|
Other stuff worth mentioning
Blazor Web Assembly code is not secure
I’m sure you already realise this, but it’s worth mentioning just in case.
The code and files for your Blazor Web assembly app can easily be viewed on the client.
Treat Blazor WASM exactly how you would any other Single Page App like React. e.g.
- Don’t include anything secret in your code
- Don’t trust the client - validate everything on the server
Resharper causes Visual Studio crashes
My Visual Studio 2019 kept crashing, disabling the ReSharper plugin solved the issue. At the time of writing, the versions were
- Visual Studio 2019: Version 16.6.5
- Resharper: 2019.3.2
Integrity Error
Sometimes, after modifying and running your code - the browser will report an Integrity Error in the developer tools console.
Doing a full rebuild of the solution solves this
Okay, I that’s all I can think of at the moment, I’ll be sure to update this if anything else comes to me