Blazor is horrible

public class Foo{
    public Foo() {
        // comment
    }
}

Let me explain.

  1. I like C#
  2. I like Razor templates
  3. Razor != Blazor

For those uninitiated, Razor is slightly questionable mix of HTML and C#. Here is an example:

@using SomeApp.Models
@model FooPageModel
@inject ISomething Something

<div class="row">
  <div class="col-lg-4">
    <h3><i class="fa fa-user"></i> @Model.Foo</h3>
  <div>
<div>

Razor had some warts, but it is a reliable workhorse, and developers can be very productive using this technology. Even when you mixed Razor with something relatively unsuitable, e.g. AngularJS, it worked just fine.

Anyway, somebody at Microsoft decided to shove a whole Javascript framework into the Razor templating system and call the result Blazor.

Actually, they called it many different things over the years. Thanks for screwing up my search results, it makes your deeply mediocre docs even worse.

This also resulted in the file extension for Blazor template files being, drumroll:

.razor

Yes, they misnamed Blazor template files as Razor files, the name of the OTHER templating language, of which Blazor is a gigantic superset. Razor files have the extension .cshtml, by the way. Amazing.

Anyway, let's get to the good part.

We want type saftety! We want a cool templating language! We want to compile a C# Backend into Webassembly and ship it in the client to run in tandem with the actual C# Backend!

If that last one seems like a bit of a stretch, then… yes. Nevertheless, it is the core concept behind Blazor. The .NET Core, if you will.

To make this happen, somebody decided to use compile time code generation to turn Blazor into a C# class with the “partial” keyword, then compile it into the backend.

Result:

Fatal flaw #1: Changing text on a website requires recompiling your entire app (and it takes way too long)
At this point, they should have trashed Blazor and moved on, because compiling a .NET Core app is not fast.
To mitigate this, there is a feature called hot reload in Visual Studio (and JetBrains Rider) that allows you to do a partial recompilation without actually restarting your app.
Or rather, it would in theory, if they had ever bothered to make that feature work properly with Blazor. Instead, 90% of the time I try to reload my changes, this operation fails. There is a gradient of bullshit on the reasons given. Here is some examples in order of ascending annoyance:
  1. Blazor code used an unsupported language feature under the hood (E.g. most of them, and also they spread like a pollution due to compilation dependencies)
  2. Runtime falsely assumes the reload works, but the app is broken afterwards.&nbsp;
  3. Complety bogus error that links you to a random file in the project. (?!)
  4. Visual Studio / Rider / .NET Runtime tries to hot reload but crashed in some way and needs to be killed (Cool)
I don’t really care that this feature is one big memory leak, or that it’s probably a nightmare to maintain. You made blazor work with compile-time HTML templates, you deal with it, Microsoft! Or I guess we can also sit in front of our apps all day, waiting seconds/minutes for them to recompile and reboot. That’s also great.

Fatal flaw #2: The world’s worst data binding / input events
You’d think they would ship a usable textbox sample in their stdlib or docs. You would be wrong. You would think they have a clean syntax for event handlers that corresponds to the native JS event names and event data types, but you would be wrong twice. You will find 5 different, contradictory syntaxes to bind to a fucking textbox onchange event, only 2 of which actually work.&nbsp;
So upon finally completing that, you will find the most disgusting bugs in your implemention, because every keystroke goes into an event queue that takes seconds to update your dom, resulting in the most user-hostile troll textbox that you ever saw, which will lag and partially remove inputs, queue up inputs, and much more fun stuff.&nbsp;

These bugs might not show up in local testing btw. And they should never have happened if the designers of blazor had done their job and&nbsp;
  1. actually built and shipped an app that works&nbsp;
  2. moved their utilities into the blazor stdlib&nbsp;
  3. documented them properly
It is very clear that they did not aim a proper modern web framework as the bar for their library. For example, data binding in child blazor components does not work two-way, and to make it&nbsp; work, you have to do absurd things instead.

The only documentation for some of this stuff that I found is inspecting the decompile source code of blazor. Which works fine but its nowhere close to state-of-the-art web frameworks which are designed for people who are actually productive and build websites quickly.


So in order to fix this mess, you will have to dig really deeply into how blazor works and&nbsp;


Related:
Anti-feature #2: Blazor Lexers are buggy and chokingly heavy, to a point where they don’t run properly on any machine
I’m guessing parsing Blazor is not easy for reasons that should be obvious&nbsp; if you look at it. They should have tightened up the razor language before making this, but instead, they extended it while maintaining full backwards compatibility.&nbsp;
As a bonus, they also left some cool obvious bugs in there, such as the parser exploding when you have razor comments inside an HTML element (when you comment out an attribute).
&nbsp;
Anti feature #5: Shitty JS Interop
We are using a&nbsp; library, in which somebody else haas nicely wrapped a JS library in a&nbsp; Blazor component.&nbsp; The problem is, when something goes wrong somewhere in its bowels, the error disapears somewhere in abstraction hell. Cool! If Blazor was created in a smart way, it would make it hard to use the JS interop without surfacing the JS error. Cool.

The little cherry on top:
Anti-feature #99: Somebody decided that “Template not imported” is a warning
I would not mind this so much if the warning level customization feature of .NET was not a clusterfuck. But it is. So I had a legacy codebase that generates a million warnings, was not able to suppress them, and somewhere in there, there was a single warning from a Blazor component was trying to tell me the very obvious reason why I does not show up. It’s almost as if you should enforce imports at compile time, in your compile time safe frontend thing whose whole point is to actually show up if it compiles (and doesnt nullref).
Ah yeah


I don’t even claim you can’t make cool stuff using blazor, but it’s just a huge pain and not even remotely worth learning. Never again.