Blazor Server Side — Looking at Single Page Apps from a different angle.
A short history lesson
In this day and age, there are more ways to build for the web than you can count. You have multiple different approaches, languages and stacks.
Until relatively recently, the preferred approach when any kind of dynamic content was involved, was to render the front end on the back end, using technologies like PHP, classic ASP and ASP.NET.
Blazor’s big selling point
This enabled Microsoft and Xamarin to produce Blazor — a new take on the client — powered by a complete version of .NET (Mono) running on WASM. This means your client code is any .NET supported language such as C# — allowing for enterprise standards in front end code.
You still need to follow the same pattern, with the front end accessing the back end via APIs etc. — but if your backend is also C#, this allows a lot of code reuse — especially around models and the like.
## Blazors twin, Blazor
## So where do we live?
When moving code from a Blazor client side project to a server side project — the first thing you will probably notice is how fast API calls are — because realistically, they aren't going across the web — both the front end and backend are running in the same place — you have direct access to the API server.
But if this is true — your front end code has the same access as the back end. You can write front end code to directly access your SQL servers, your file system etc. You probably shouldn’t but you can.
Blazer server side lives in this beautiful middle ground between the old and the new. The fluent and responsive UI of JS frameworks, but the power and control of the old server side frameworks. It’s not perfect, but its close — and its constantly improving.
## What does that mean?
Lets think about front end paradigms that are new and interesting from an SPA point of view:
* Secrets are secret: Private keys can be consumed in the front end — and remain private.
* If its on the server, its in the front end: The filesystem, other machines on the LAN, ports behind the firewall — the lot — its all accessible.
* You control the performance: While you are running every users front end and thus its a heavier load, you get to define the resources — you don’t need to worry if an end user has enough CPU to render your massive list in a reasonable time etc. — the users browser is just a thin client.
* Its possible to share between sessions/clients: Caching becomes almost irrelevant when you can have data in a static global.
Do I really want to do that sort of thing in client code?
tl;dr — probably not. That said, if it was okay (and secure) in things like asp.net webforms — its still ok.
Firstly, the front end doesn’t need an API anymore — but you probably still do. Often the API is consumed by more than the website. That alone is a reason to not just tear out the API and put all the code in the front end, but you don’t really want to manage two versions of the same code.
If you’ve been a responsible developer and your API Controllers are very thin via a service or even better, by using the mediator pattern (with something like Mediatr) you have a great option; simply call the same code that the API would. This alone can give your app a massive boost. No HTTP requests are required, translation too and from JSON aren’t required, generally it is a thinner path.
Once this is in place, you then have a decision to make: API controllers/methods which are entirely there to service the front end — can they be removed. The smaller the footprint of an API, the smaller the attack vector.
Once you are in the land of having a service that provides more than the API things get even more interesting. Your functions no longer need to be serializable. Nor do they need to be a “reasonable size”.
Lets look at an example. You have an online store. Your fetch products call can return images as images just as a field within the model if that makes sense. You can fetch the entire product catalog in one fetch — if you need to; something static like this can … be static. If user a) has viewed the store, the data is already available. The view can still be paginated if that gives a better user experience, but you get the ability to VERY quickly use LINQ queries; resort the data, apply filters etc. — at lightening speed — there’s no API call and there’s no DB hit.
If you want to get very tricksy, there are some amazing options open. Lets say this store has a list of recently purchased items. Usually this would either be set on a schedule, once on page load or polled. With everything in the same domain, this could be completely event driven — it doesn’t even need to be tied to the database.
Things to consider
Now, if you’re like me, this is sounds very whizzy. That said, its not quite as simple as that.
Everything in the previous section can be true — everything being in the same domain, on the same server. But this assumes only one server. If you have a larger site, there is a good chance you are using a scale out pattern — spinning up new servers when load requires — and maybe even spinning down ALL servers at times of zero traffic. That means while sessions can share static variables, not every session can share the SAME session variable. With the last example we gave, the list of purchased items — this means if user A is on server 1 and buys something, then user B who is on server 2 will not receive the event. In some scenarios this is acceptable, but many it is not.
There are work arounds for this. Azure Webapps for instance has a local folder — that’s actually shared across all instances. This can be watched for changes.
Even if you have to resort to polling the DB, this can be done at the server level rather than the session level. This sort of thing goes a long way to offsetting the extra load of hosting — if you have 500 users spread across 5 servers, what would have been 500 API calls before (which likely would have been cached to some extent) you now just have 5 DB calls.
Security just got a whole lot easier
Beyond reducing what you expose to the wider world, Blazor Server Side flips the security problem on its head when compared with JS frameworks. As we all know, any code within JS is public. Its run on the client so must be sent to the client. This means you have no ability to hide. Private keys aren’t private so just aren’t an option. Obviously this is already a solved problem, but in this world, client code IS private. Private keys ARE private. How does this help?
Well, you need the client to go hit twitter with your dev API key? That’s totally fine. Since code is only on the server, it becomes very difficult for secrets to leak and thus security almost becomes brainless and doesn’t need to be a consideration. Of course, it should still be considered, but the pressure is somewhat lifted.
With great power comes great responsibility
This is a lot to take in. What am I learning here?
Blazor Serverside requires you to think about your website from two different angles. These are not new angles, but never before did you really have to consider them at the same time.
Overall, you think about your front end the same way you’d think about a webforms project — or even an API — whilst still considering the front end. Blazor’s front end is VERY opinionated about how you do things, but with that comes very simple code for doing crazy dynamic things. This coupled with the power that being server side gives you opens up some amazing options if you spend a bit more time thinking about how to architect.
Build your first Blazor App
A fantastic set of videos to get you up and running on Blazor
A friendly bunch of passionate Blazor devs who are always happy to help out those just starting.
## Chris Saint’s blog
The general C# world has Jon Skeet. Blazor has Chris Sainty. Rather than scour stack overflow for the answer your question, Chris probably already has a working example on his blog.