I’ve recently blogged about how excited I am by the promise of Blazor. Well, I’ve built my first Blazor app and, having tried it, I’m no less excited. There are still plenty of rough edges (which I talk about below), but it fundamentally works. In this post, I’ll try to outline the pitfalls as best as I can, in the hope that others find it useful. Please don’t construe anything I write as a criticism of the Blazor team – what they’ve done is already game-changing.
In my last post, I was already gushing about the opportunities I saw in the early Blazor demos. When I saw on Thursday that the team had released their first public preview of the tooling, I couldn’t wait to get started. Thanks to my pesky job and peskier son, I couldn’t actually get started until the weekend. Even still, I was able to publish my first Blazor app today: contabsblazor.azurewebsites.net
It’s a silly little app right now. All it does is demonstrate some of the different ways that ConTabs can render a table. Trivial stuff really, but it’s enough to demonstrate the potential – code written in C# can run in your browser and can reference any library compatible with .NET Core (including ConTabs).
In due course, I can definitely see the value in expanding this demo to include other features of ConTabs. More broadly, I think this may well become a standard way of augmenting documentation with examples. (Not that I think that’s the limit of what people will do with Blazor. To the contrary, it’s just the least imaginative use and therefore the one that springs to mind.)
In this post, I want to share some of the lessons I learnt during the development process. These include the heftiness of the requisite tools, the persuasiveness needed to deploy, and the footprint in production. The first two of these will likely fade away as Blazor becomes more mature, but the third is going to require some crafty thinking.
Getting the tools
Because I’m on terrible rural internet, getting all the right tooling installed took me an age. Set aside some time to do this and try to sustain your enthusiasm!
None of it has been properly released yet, so you’ll need to get the latest preview versions of the .NET Core SDK and Visual Studio 2017. I think these combined were about 1GB. If you routinely surf the bleeding edge, you may well have recent versions of the previews installed already, in which case I should think you’d be looking at a somewhat slimmer download.
Then you’ll need the Blazor-specific bits, which are available in the extension marketplace. This is the secret sauce that contains the project templates that make this possible.
As I said, I’m on atrocious rural internet. Downloading all this took literally hours. If I weren’t so enthusiastic about what Blazor is offering, I think I might have given up. If you’re on a decent connection (e.g. at work), you may find it much quicker.
Anyway, this issue will certainly dissolve away as Blazor matures. When it is stable, I have no doubt it will be included in the main VS package. Perhaps Blazor will get made into a “workload”?
This was super easy. Anyone who has ever done any work in Razor will find this very natural. I followed the instructions in the announcement and can’t really fault them.
I did have one issue when I tried to use an
onchange() method, but using an
onclick()was viable for me, so I dodged any real sort of problem-solving.
The binding of DOM elements to data in .NET objects was a pleasant surprise. All you have to do is add a
bind()attribute to the element you want to be bound. Then it just works. Very nice.
All in all, it took me mere minutes to get an app doing what I wanted it to do. A bit of copying and pasting from an existing demo app, a little bit of wiring-up, then a little bit more of styling etc., then… done! The lack of debugging in the current preview release might put me off doing anything much more advanced for the time being, but maybe I’m just chicken!
If you’re curious, all of my code is in a new GitHub repo: ConTabsBlazor.
With a working application, I naturally wanted to share my work with the world. This was perhaps the most frustrating aspect.
Attempt #1 – FTP and Apache
My naive understanding of web assembly had led me to believe that I could just grab the files and dump them on my main web server via FTP. Suffice to say: this did not work. A superficial examination revealed that I was probably going to have to configure new MIME types on my server, as well as unravelling the baked-in assumption that Blazor apps are going to live in the web-root (i.e. not in a subdirectory).
One day soon I’ll dig into these issues properly. There’s no fundamental reason why a Blazor app couldn’t be served from any HTTP server. I mean, I’m doing absolutely no back-end processing – just serving up static files to be interpreted by the browser. For now, I’ll get back in my box and follow the script…
Attempts #2 – #5
The instructions in the announcement post say to publish to Azure. I’d opted not to do this initially. I’d wanted it on my own website and I didn’t fancy paying for a new Azure app service. When that wasn’t straightforward, I trotted back to Azure with my tail between my legs.
Except that using Azure wasn’t a silver bullet.
My first Azure attempt was to publish my Blazor project to an App Service. Just like the instructions suggest. Unfortunately, I was presented with a “502.5 error”. The link on the error page suggested that this is related to the combination of ASP.NET Core and IIS, but there didn’t appear to be an obvious, straightforward resolution. What struck me as odd is that the instructions I’d been referring to made no mention of needing to perform any such steps. I’d clearly done something wrong, but what?
Perhaps I’d selected the wrong sort of App Service? The screenshots in the announcement post only have one type “App Service”, but on my computer I was also offered a Linux variant. This seemed like it might work, so I gave it a go. This time I didn’t get the IIS error (naturally), but instead I was simply presented with the default “your App Service is ready” screen and a link to the quickstart guide.
Looking back at The Instructions made me realise that I had chosen a particular path very early on. When choosing which flavour of AST.NET Core to use, I had selected “Blazor”. This means I had not selected “Blazor (ASP.NET Core hosted)”. I had deliberately gone for the version without the back-end, as I just don’t need it. But what if I had selected it?
My third attempt involved porting the code I’d written into a new project using this second template. Bit of a faff, but didn’t take long. I deployed this to a Linux-based App Service and got… (drumroll please!) “SERVICE UNAVAILABLE”.
“Oh well,” thinks I, “I’ll just check the final combination, just to be sure…” And lo! Deploying a project based on the “Blazor (ASP.NET Core hosted)” template to an IIS App Service was all it took. It worked! Hallelujah!
|IIS App Service||Linux App Service|
|“Blazor” template||Error 502.5||Default page|
|“Blazor (ASP.NET Core hosted)” template||Worked!||SERVICE UNAVAILABLE|
Hope this helps someone else. It took ages (crappy broadband remember) to work out!
Longer term – bloat
Now that I’ve got it working, my mind turned to more philosophical questions. The main thing that spring to mind is the wisdom of requiring users to download a web assembly version of the full Mono runtime.
In practice, it’s not that huge. My demo is pretty snappy (even on my internet connection). And the benefits are obvious. I mean, if I didn’t have access to the proper runtime, I’d be forever worrying about what I could or couldn’t do, or working out how to shim in some particular NuGet package. Not ideal.
Still, it feels like there ought to be a better way. I think others have suggested using CDNs to share the load for the core runtime files. Ahead Of Time (AOT) compilation has also been suggested, so the web assembly file would only contain the code necessary to make the app run. I can see both options helping dramatically, but they would seem to be mutually exclusive. My money is on caching via CDNs, but this will require uptake to reach a critical mass before it is effective.
Like Neo leaving the Matrix, I have swallowed the red pill. The new world isn’t pretty (yet), but boy is it where I want to be.
I think the one thing I’d like readers to take away from this post is “it works“. We shouldn’t forget how revolutionary this is. If someone had told me a year ago that we’d be running .NET in the browser, I’d think they were pulling my leg. Yes, we had Google’s NaCl, and no, web assembly isn’t really that new, but it still didn’t seem like we were going to be able to run C# in the browser anytime soon.
If you’re going to give it a go, I hope the notes in this post are useful. The big thing for me is deploying. At some point, I’ll revisit this and see if I can’t get it working on my creaking old Apache server.
If you’d like to play with what I’ve done, use the following links:
Finally, big props once more to the team behind this. If you haven’t already, go read their announcement and tell them how awesome they are!