Blazor WebAssembly .NET5 – First look and some gotchas
What is Blazor WebAssembly?
Blazor can be described most simply as a frontend framework like Angular but instead of JavaScript or TypeScript we get to use C# (that is where WebAssembly comes into play). Because we are using C# for the frontend we can share some code between the front and back and lets face it, use a language that we are comfortable with.
There are some drawbacks to such as the initially load time is likely to be slower because the client has to download the assembly before they can get started.
There is a Server based model for Blazor which does not rely on WebAssembly and instead does most of the processing server side. you can get a much better explanation of it here.
Identity gets complex
Like any client sides technology, handling authentication always becomes a little more complex than using a cookie based approach. This has been something that I have always felt held me back from using SPAs in the past. You have to investigate methods such as OpenId to exchange tokens. This is not anything new for say mobile app development but it is more complex to get your head around then the cookie based. The tooling around OpenId is dependant on third party packages such as IdentityServer. Would be nice if this part of the framework but there is plenty of support and documentation.
Helpful Blazor Project Template
The Visual Studio Blazor template thankfully comes with IdentityServer already setup which saves you a lot of time learning. Its also runnable from the start, running your backend server in debug while also running the client. One thing I wish the template had setup was an example of authenticated POST of data and linking that data to the logged in user.
Trouble getting the Logging in User in the Controller
One early issue I had was getting the current logged in user object using the User Manager. Running say:
var user = await _userManager.GetUserAsync(User);
would always return null even though User had a valid identity. Turns out this is related to GetUserAsync looking at the wrong claim to get the users Id . You can therefore use something like below to get the users Id then look up the user using the DatabaseContext
var id = User.FindFirstValue(ClaimTypes.NameIdentifier);
return _context.Users.FirstOrDefault(x => x.Id == id);
What is the upfront download / loadtime?
As a debug build with the Blazor template we are looking at 9.6Mb download on first load but they do fire out a console log message promising it will be smaller when you publish. So after a publish we are still looking at 3.7mb weight which admittedly not that bad considering its including some bootstrap styling and all the logic and should only be at the initial visit. As a really unscientific measure the initial load times even with the resources cached takes 10-15 seconds which would be impractical for a simple website but I suspect it would be understandable for a complex application that users would expect some load time.
The Client can be hosted anywhere?
Yes but you do need some sort of server to help with routing for example if you go to test.local/things then you need a server to route /things to the index.html. I was able to get the Client running on a local Apache LAMP setup using the configuration discussed here
I did a separate post: blazor webassembly on a different host to the server which explains the process I went through to setup the Client on a different host to the server.