Back to All Posts

Blazor, a C# Friendly Single-Page Application (SPA) Framework

Nowadays, when we talk about web applications, in 99% of the cases, we talk about a REST API (or REST-ish) with a client app written in Angular, React or Vue.js.

We know that, according to the norm, we will get scalability and other ilities by designing our apps in such a way. And that’s the way to do it. The result is a modern app, aligned with trends and with an up to date technology. Fair enough, as we know that those APIs are there to stay and the server-side is stable. But when it comes to the client-side…not so much.

We have many frameworks that do mostly the same things. Some are easy to configure, some not quite. We often get updates on those frameworks, which is a good thing. But if it were to always keep the apps up to date, we would have to spend valuable development time only on the client-side app to upgrade to new framework versions.

Blazor, yet another UI framework! Why should I care about another one, only because it has Microsoft and the community behind it? They will end up doing the same things as the other frameworks anyways.

Well, first you should know and care about it because it will allow you to reuse your C# coding skills and .NET Core while giving you pretty much everything the others have to offer.

 

So, what is Blazor?

Basically, Blazor (= Browser + Razor), is a single-page application (SPA) oriented and comes with two stable hosting models (for now). It is very similar to React, Angular and Vue.js, and can run in the browser on top of WebAssembly.  By combining it with Razor, that has been around since 2010, Blazor aims to be a neat solution that fits perfectly in the .NET ecosystem, with language and familiar tooling.

Blazor is still in an experimental phase, but it offers pretty much what you are used to on the server-side – dependency injection, model validation, one-way data binding, and what you need on the client side – JavaScript interoperability, routing, two-way data binding, form validation, event binding and so on.

In other words, Blazor is a collection of self-contained C# and HTML pages named components, that can be beautified with CSS. The syntax used is familiar to most developers that worked at least once with ASP.NET Core MVC, as it’s simple Razor with context switches and a few new syntax components.

 

Blazor and WebAssembly

The history of WebAssembly starts in 2015 when a group of people from all the major browser vendors got together with the idea to create a new type of code, that is faster than JavaScript. They defined a standard for it, much like HTML and CSS. By the end of 2017, all browsers supported the MVP of WebAssembly.

It doesn’t have the intention to replace JavaScript but to complement it. It runs in the same sandbox as JavaScript does, sharing the same security features and policies, and having access to the same things JavaScript has.

Being the new kid in town, this doesn’t mean that WebAssembly will be the norm in the next years, but there will be cases where apps might need some lower level computations, or faster computations (like SIMD).

WebAsembly is designed with portability and performance in mind, and some tests show that on certain cases, is 6x-20x faster than JavaScript.

The performance comes from the fact that WebAssembly was designed to be a much lower language than JavaScript. It means the files are much smaller that minified JavaScript and the purpose wasn’t to write code directly in WebAssembly but to target WebAssembly by compilation. Due to the file structure, portions of them can be compiled in parallel, or parsed and validated quickly.

“Any application that can be written in JavaScript, will eventually be written in JavaScript.” — Jeff Atwood, Author, Entrepreneur, Cofounder of StackOverflow

If this is true, WebAssembly might be your way out because it gives you the opportunity to reuse some existing server-side code. More than this, it opens the door to developers that don’t like React, Angular, Vue.js or others, or can’t use their preferred language directly in the browser or outside the browser.

 

Getting started with Blazor

To be able to run one of the two Blazor models you need to install the ASP.NET Core Blazor Language services from here, and to make sure you have 2.1 SDK installed.

This will install into your Visual Studio the templates you need to start playing with this new technology.

 

Install ASP.NET Core Blazor Language Services

 

Client-Only Blazor Project

The client application is very similar to what we already know from ASP.NET MVC Core.

  • The wwwroot folder contains all the CSS, JavaScript, and libraries needed in the page;
  • Pages –the Blazor components used;
  • Shared – similar to MVC, contains the layout and everything that can be shared to avoid duplication.

 

Blazor Client-Side Structure

 

With just a few keystrokes you’ll be able to obtain something like this:

 

Get Started with Blazor

 

The code behind is simple and intuitive:

 

@page "/shopping-list"

<h1>Shopping List</h1>

<p>Number of items in shopping list: @currentCount</p>
<label for="newItem">Add new Item</label>
<input type="text" name="item" value="" bind="@Item" />

<button class="btn btn-primary" onclick="@AddToList">Add to list</button>

<ListItem ShoppingItems="@ShoppingItems"></ListItem>

@functions {

    [Parameter]
    private string Item { get; set; }
    int currentCount = 0;
    List<string> ShoppingItems = new List<string>();

    void AddToList()
    {
        currentCount++;
        ShoppingItems.Add(Item);
    }
}

 

Notice the ListItem element that is similar to an Angular component or a RenderPartial view in MVC. It does nothing more than iterate through the passed parameter and display it.

 

ListItem.cshtml

<ul>
    @foreach (var item in ShoppingItems)
    {
        <li>@item</li>
    }
</ul>

@functions
{
[Parameter]
List<string> ShoppingItems { get; set; }
}

 

As other client-side frameworks make use of directives, Blazor also supports directives.

  • @page – takes care of routing;
  • @inject – brings the power of DI container in your component;
  • @functions – adds C# block to the current component enabling you to pass parameters to other child components;
  • @addTagHelpers – imported from MVC, brings the power of different Razor helpers in Blazor.

 

Server-Backend Blazor Project

The second project type – Blazor (ASP Core hosted) – generates three projects in your solution.

  • Client – similar to the first kind of project;
  • Server – a classical, barebone API that has response compression enabled, and uses Blazor as a middleware;
  • Shared – a library that will hold ‘Models’ shared between Client and Server.

 

Blazor Server Backend

 

In this model, you’ll have the Web API with all the conventions you are used to (bindings from body or query, routing, routing constraints), and you’ll need to make server calls from the UI just as you do with any other client-side framework.

 

ShoppingListController.cs

   [Route("api/[controller]")]
    public class ShoppingListController : Controller
    {
        private readonly IShoppingListRepository shoppingListRepository;

        public ShoppingListController(IShoppingListRepository shoppingListRepository)
        {
            this.shoppingListRepository = shoppingListRepository;
        }



        [HttpGet("[action]")]
        public IEnumerable<ShoppingItem> Items()
        {
            return shoppingListRepository.GetAll();
        }

        [HttpPost]
        public ShoppingItem Items([FromBody] ShoppingItem item)
        {
            if (ModelState.IsValid)
            {
                shoppingListRepository.Add(item);
            }

            return item;
        }

    }

 

In the client side, you will need to use the @inject directive to make HTTP calls using the HTTP Client, and the @using to make sure you reference the models in the Shared library.

 

@using ServerBackend.Shared
@page "/shopping-list"
@inject HttpClient Http

<h1>Shopping List</h1>

<p>Number of items in shopping list: @currentCount</p>

<label for="newItem">Name</label>
<input type="text" bind="@Item.Name" />
<label for="Brand">Brand</label>
<input type="text" bind="@Item.Brand" />

<button class="btn btn-primary" onclick="@AddToList">Add to list</button>
@if (ShoppingItems == null)
{
    <p><em>Loading...</em></p>
}
else
{
    @foreach (var item in ShoppingItems)
    {
        <p>Name: @item.Name</p>
        <p>Brand: @item.Brand</p>
    }
}


@functions {

private ShoppingItem Item = new ShoppingItem();
int currentCount = 0;

protected async Task AddToList()
{
    ShoppingItem addedItem = await Http.PostJsonAsync<ShoppingItem>("api/ShoppingList", Item);

}

List<ShoppingItem> ShoppingItems;

protected override async Task OnInitAsync()
{
    ShoppingItems = await Http.GetJsonAsync<List<ShoppingItem>>("api/ShoppingList/");
    currentCount = ShoppingItems.Count();
}
}

 

Regarding errors, if something goes wrong, you’ll surely see it in the developer’s tools, just as you would see for JavaScript. For some of them though, you might not realize what is wrong at first look, because you’ll be tempted to ask yourself: ok…now…how do I get in blazor.webassembly.js?

 

Potential Blazor Errors

 

Blazor Hosting Options

So far, Blazor offers two hosting options – client-side hosting and server-side hosting. As they both come with benefits and drawbacks, I invite you to try them and decide which one better fits your project.

 

Blazor Client-Side Hosting

One of the major issues of the Blazor client-side hosting (that Microsoft is trying to solve), is that the application will load everything in the browser and the size of it might be bigger than expected or needed.

We can’t force the end-user to add a little extra RAM to his machine, just to be able to browse your app. We already know that some browsers are already consuming a lot of resources – and with this model, you’ll just end up serving it more resources.

 

Blazor Server-Side Hosting

The server-side hosting model for Blazor tries to separate the UI from the server, decreasing the load from the browser (compared to client-side hosting), and moving it to the server.

If you can afford a scenario where UI updates, event-handling and JavaScript calls (pretty much everything), are handled from the good old server through SignalR connections, this may be perfect.

While you might get a small client-side footprint, a faster startup and increased speed on communicating with the server, you might lose a lot on latency and scalability.

You always need a connection with the server, and moreover, the server needs to handle multiple connections with the client. Once the server goes down, or your internet goes down, you won’t be able to work offline, not even for a little bit. In this case, I think you can also forget about caching resources, and all the tricks you use to deceive your end-user in believing that everything runs smooth.

Even so, if you move your server to the cloud, in a data center that is close to your end-users, you might solve a little latency and ensure that your server is available a decent amount of time.

 

Conclusions

Blazor is a very interesting, yet experimental, project. Even if it’s not ready for production right now, it’s worth to keep an eye on it, at least to see how they will solve the size and the load time issue for the client-side hosting model.

Even with a stable version shipped, it doesn’t mean that you won’t need Angular, React or Vue.js.  Some frameworks have messy ceremonies or major changes in new versions, but every framework has its rightful place in the web ecosystem. And surely Blazor will have its applicability and enthusiastic developers pool.

With open-source and strong tooling in mind, Microsoft promises that the Blazor with server-side hosting will be part of ASP.NET Core 3.0 later this year.

About the Author

Senior Software Developer

Irina

Software architect, Microsoft Certified Trainer and MCSD for Web and Application Lifecycle Management. Above all, passionate about leadership and personal development, as well as creating learning contexts for her team.

2 Comments

  1. john September 12, 2019

    Hi Irina,
    This article helped me to update my knowledge in Blazor. Thank you.

    Questions:
    Does Blazor supports SQL Server 2008 R2 for CRUD operations?
    If so, How?

    Thanks,
    John.K

     
  2. Irina Scurtu September 13, 2019

    Hi John!
    On the server-side you layer your application in any way you want having whatever it suits you as a data store. SQL Server, PostgreSQL or anything else. If you are able to reference it from your main app and is compatible, it will work. From Blazor you won’t interact directly with SQL Server, you will still need to have a layer/library that will allow you to get data back and forth to the data store, just as in any other kind of application.

     

Your email address will not be published. Required fields are marked *