Unlike prior efforts at getting C# to run client-side, Blazor isn’t transpiling or doing any other fragile tricks: instead, it’s got an actual .NET runtime that loads and runs standard .NET assemblies via WebAssembly (or asm.js for older browsers). This means you get full-fidelity .NET - everything behaves exactly like .NET on the desktop/server.

If you want a demo of what it’s like to build an app with it, watch 5 minutes of this video from NDC Oslo.

I’ll say this again later, but to be sure you’re clear: this is an experiment, and it’s not an official Microsoft product.

Backstory: it started with DotNetAnywhere (DNA)

Back in April, I was trying to think of ways to run .NET under WebAssembly, when coincidentally I stumbled across an HN comment about DotNetAnywhere (DNA), a .NET runtime I’d never heard of before. A quick look at its GitHub repo showed that it’s incredibly compact - the whole implementation is just a handful of plain C files. Its extreme simplicity meant that, even though it well predates WebAssembly and hadn’t even been maintained for over 5 years, it only took a few hours and a few minor tweaks to get it compiled as a WebAssembly binary. To my great surprise, it loaded and executed simple .NET assemblies on the first attempt without any complaints.

Blazor, an app framework

Blazor takes this basis and lets you build an app with it. It uses Razor files, which combine C# and HTML markup, to define components that present your data and update when anything changes (a bit like React or Angular components). It also inherits Razor Pages concepts such as layouts and so on.

This is purely experimental. You can’t build a production application with this, for so many reasons. It exists as a way of finding out what a .NET-based SPA framework might look like, and whether people would have any interest in it.

Nonetheless, some folks from the ASP.NET team and some community members have become interested and contributed a bunch of great enhancements, such as ncave doing some very impressive low-level work to improve DNA, and David Fowler and Stephan Halter from the ASP.NET team getting prototype debugging support working as part of a team hackathon event.

Hitting limitations in DNA

It’s extremely impressive that Chris Dunelm single-handedly created an incredibly compact .NET runtime, so compact that the whole thing (including assembly execution, garbage collection, threading) compiles down to 60KB of WebAssembly. Yes, seriously, 60KB - that’s not a typo - and it does actually work. For more about DNA, see Matt Warren’s post.

But it’s probably not the future. Chris stopped working on DNA about 6 years ago, so it’s a long way behind a modern .NET runtime. It lacks some critical things such as proper reflection support and working with netstandard assemblies, and there are some known bugs such as crashing with certain types of generic method invocations. And when it crashes, it gives you basically no clue about why.

During the ASP.NET team hackathon, the thing that most commonly frustrated and slowed people down was not being able to rely on having the complete standard .NET base class library, and not really knowing what runtime features were supported. So .NET in the browser can only be viable if there’s a true, robust, complete production-grade runtime that can run on WebAssembly/asm.js. But where would a miracle like that come from?

Mono on WebAssembly

Not content with just running Mono on all desktop/server platforms, plus iOS/watchOS, Android, smart TVs and the like, Miguel de Icaza from the Mono team has announced a plan to bring it to WebAssembly. And now, Rodrigo Kumpera is just one pull request away from getting WASM-capable Mono interpreter support merged into mono:master . This is exactly what’s needed: a proper, performant, robust, and feature-complete modern .NET runtime on WebAssembly - under active development by a whole team, no less :)

Blazor on Mono

Based on Rodrigo’s excellent work, I’ve migrated Blazor to run on Mono. The result is that it has the same features as before, minus the prototype debugging support, but now it executes faster and it supports a vastly more complete .NET API surface, and virtually every aspect of the runtime works correctly like on desktop/server. It even (usually) provides sensible error messages if you cause unhandled exceptions.

Getting started

If you want to try it out, install the prerequisites:

VS2017.3 or later

.NET Core 2.0 SDK

… and then install the 0.3.0 (or later) build of Blazor.VSExtension.vsix, the VS project template. Then you can do File->New Blazor application and follow along building an app like in this demo.

Caveats