The long way to .NET in the browser
I started my first coding experiments around the year 2000 with Visual Basic 6. Not too much later a teacher at school told me about something new called ‘.NET’. So, in 2002 I switched from VB 6 to .NET and C#, and since then, nothing could convince me to switch technology again.
However, when you build your backend with .NET, you still have to use a different technology for your frontend development. This means you either have to learn both or you need different people for each job. And everyone who worked with client-side web technology knows that it’s not just learning a new language or framework. It is a completely different ecosystem of tools: NodeJS, npm, Yarn, webpack, to name just a few.
When I read the announcement the first time, I was really excited. But at that time, the project was still very experimental. This changed recently. On September 23rd, 2019, the first variant of Blazor (Blazor Server Side) was officially released together with ASP.NET Core 3. And the second variant (Blazor Web Assembly) is planned to be released in May 2020.
I thought now is the right time to take a closer look. There are plenty of articles available, but I wanted to know if it’s ready to be used in production. That’s why I started to port an existing application, which we created for a customer, from Angular to Blazor. The backend is an ASP.NET Core REST API, so the hope was to be able to re-use some code.
In a series of blog posts, I want to write about my experience of porting this project and about different aspects of Blazor I think might be interesting for others.
After this long introduction, it’s time to jump into details. Let’s start with a short overview of Blazor.
What is Blazor?
When you think like me, then the first and most important question is: why is it called Blazor? The most trustworthy source I found to answer this question is the QnA page on GitHub:
Blazor makes heavy use of Razor, a markup syntax for HTML and C#. Browser + Razor = Blazor! When pronounced, it is also the name of a swanky jacket worn by hipsters that have excellent taste in fashion, style, and programming languages.
Now that this is clarified, we can continue with what Blazor is.
As said before, the best part is that Blazor uses only open web standards. It runs on all modern browsers, on desktop and mobile, without any additional plugin. How it works depends on the hosting model. Currently, there are two main hosting models available: Blazor Server and Blazor Web Assembly. At DotNetConf last September, Microsoft announced a few additional hosting models that might be available in the future. These additional models go beyond web apps and will also support desktop and mobile apps. Let’s take a closer look at each.
This model is currently the only one that is officially released and supported. With Blazor Server, your app runs on the server, not in the browser. It uses a SignalR connection to send UI updates from the server to the browser. Microsoft developed an efficient algorithm to calculate the diffs and transfers them in a compact binary format.
Unlike most web applications that usually use a state-less approach, Blazor Server applications hold the state on the server. For developers, this requires a rethinking in some cases. But in general, you use the same concepts as in any other ASP.NET Core application.
In my opinion, one of the biggest advantages is you don’t need to create an API to communicate between client and server. Everything runs on the server, so you can directly call into your business logic.
And because all the computation happens on the server, Blazor Server apps are a good fit for thin clients and low-end devices.
When Microsoft announced Blazor the first time, it was only about the WebAssembly model. And for me, this is the most exciting and fascinating model. It allows us to run pure .NET code in the browser.
To make this possible, the Xamarin team compiled the Mono runtime to WebAssembly. WebAssembly is a binary instruction format that allows running code in the browser with near-native performance. It is an open standard and is supported by all major browsers for some years now.
A Blazor WebAssembly application first loads the runtime in WebAssembly binary format. After that, it loads our application assemblies and all its dependencies. The dependencies also include the framework itself, including System.dll, mscorlib.dll, etc. Only the runtime is in WebAssembly binary format. All other assemblies are in the same .NET assembly format as you would use in a usual .NET application.
Usually, in .NET applications, a Just-In-Time (JIT) compiler is used. JIT compilation is currently not supported in WebAssembly but might be added in a future version of the standard. For now, an interpreter is used to execute the .NET code. Microsoft is also working on Ahead-of-Time (AOT) compilation and plans to release it with .NET 5 in November. With AOT compilation, we can compile all application and framework assemblies to WebAssembly. This compilation will result in a longer build time but will improve the performance at runtime.
Progressive Web Apps (PWA) are just web apps that make use of modern web standards to deliver a native-like experience. This includes, among other things, offline support, push notifications, and install-to-home. Even though an installed PWA looks like a native app, it’s still a normal web app that is limited to the browser’s APIs and sandbox.
You can take nearly any web app (not only Blazor) and make a PWA out of it by adding a few files. Speaking of Blazor, the WebAssembly model is a better fit to be used as PWA. You can, of course, make a PWA with Blazor Server, but it requires a constant connection to the server to run the application.
It is already possible to build Blazor PWAs today. But Microsoft plans to add additional templates and better tooling support in the future.
The Blazor Hybrid model is currently in an experimental state, and there are different approaches available. The goal is to distribute a Blazor app as a native desktop application. It allows us to use native features of the operating system, but it still uses web technology to render the app. That’s why it’s called a hybrid approach.
A popular open-source framework to build native applications with web technologies is Electron. Electron uses Chromium and Node.js to run the apps locally. It is used by Spotify, Microsoft Teams, Slack, and many others. And we can also use it together with Blazor. Microsoft added an experimental sample project on GitHub.
Another experimental approach is WebWindow. Instead of using Chromium and NodeJS (which results in large installer packages), it uses a native OS window with a browser view (Chromium-Edge on Windows, WebKit on Mac, WebKitGTK+ 2 on Linux). WebWindow can reduce the download size of a hello world app from around 60 MB (with Electron) to below 1 MB.
An interesting aspect is that in both cases (Electron and WebWindow), we use neither a SignalR connection nor WebAssembly. The Blazor app runs on native .NET Core (bundled with the app or installed on the system) and communicates directly with the browser window.
On January 14th, Microsoft announced a new experimental project to enable native mobile app development with Blazor: Experimental Mobile Blazor Bindings. With Mobile Blazor Bindings, we can use Razor syntax to describe the UI and bind to Xamarin.Forms elements. The Xamarin renderers are then responsible for rendering the UI with native elements on each platform.
The Blazor Mobile Bindings are experimental, but they use the existing Xamarin.Forms infrastructure and ecosystem. If you are interested in how the two things are connected, you can take a look at the architecture overview.
I hope you are now as much excited about Blazor as I am. Blazor allows us to use C# and .NET to write single-page web applications. We can run the applications either on the server or directly in the browser. With Blazor Hybrid and Mobile Blazor Bindings we can go even one step further and build desktop and native mobile apps. And this is just the beginning. Let’s see what comes next.