Let's talk!

Maciej Szymczuk
Regional Director
USA

(+1) 929 262 9149

maciej.szymczuk@softwarehut.com


contact form

Let's talk

Blazor is quite a new technology.

It has been shipped with the recent .NET Core 3.0, but was available earlier, in preview versions. Blazor enables developers to write web UIs using C# instead of JavaScript with the help of Razor markup syntax.

This means that we can use just one language across the whole web stack, like JavaScript in MERN or MEAN, to build business logic, as well as dynamic functionalities on the client-side. Apart from being a web-oriented framework, Microsoft plans on rolling out support for desktop and mobile platforms.

Sounds cool, doesn’t it? Now, let’s see it in action!

Blazor hosting models

Before jumping into coding, there is one important thing to consider – the hosting model. Currently, there are two available:

  • Blazor WebAssembly
  • and Blazor Server.

The latter might be for production use; however, Blazor WebAssembly is still in its preview edition.

Blazor WebAssembly

Blazor WebAssembly runs a client application directly in the browser. While requesting it from the server, .NET runtime environment is downloaded and initialised along with the application. This makes for longer loading time, but eventually the app is fully-functioning, locally, and without any .NET server-side dependency.

Blazor Server

With this model, the client application acts as a thin client. It connects to the server over the SignalR endpoint, and updates accordingly with incoming messages. Most of the heavy lifting moves server-side, which involves maintaining the client state and computing UI diff.

For this article, we will stick to the Blazor Server because it is easier to debug and generally requires less hustle.

Learning by example

To explore Blazor functionalities, I have built a tiny social network app. Source code is publicly available on GitHub along with the list of implemented features.

The project stands by the graceful name ‘Croaker’, and it enables users to share their thoughts in the form of short messages, labelled with hashtags.

Creating components

Having some background in React or Angular, it is fairly easy to get used to the Blazor. One of the similarities are Components, which are reusable units of UI elements with dynamic functionalities attached to them.

They typically contain declarative UI code along with the implementation of component members in one file. They can split into separate files, but this approach is not recommended.

In the example below, you can see the implementation of the Croak component – an interactive card containing short messages with additional information such as the author name, or likes’ count.

For the sake of simplicity, styling has been omitted, with complete source code available on GitHub.

@using System.Collections.Generic
@namespace Components

<div>
    <div>
        <blockquote>
            <p>@Content</p>
            <footer>
                <small>
                    by <cite><a href="/byUser/@AuthorName">@AuthorName</a></cite>
                </small>
                <a @onclick="OnLikeClick">
                    <span>@LikesCount <i class="material-icons croak-icon">thumb_up</i></span>
                </a>
            </footer>
        </blockquote>
        <div>
            @foreach (var hashtag in Hashtags)
            {
                <a href="/byHashtag/@hashtag">#@hashtag</a>
            }
        </div>
    </div>
    @if (IsDeletable)
    {
        <div>
            <a @onclick="OnRemoveClick">
                <span class="material-icons">delete_forever</span>
            </a>
        </div>
    }
</div>

@code {
    [Parameter]
    public string AuthorName { get; set; }
    [Parameter]
    public string Content { get; set; }
    [Parameter]
    public IEnumerable<string> Hashtags { get; set; }
    [Parameter]
    public int? LikesCount { get; set; }
    [Parameter]
    public bool IsDeletable { get; set; }
    [Parameter]
    public bool IsLiked { get; set; }
    [Parameter]
    public EventCallback OnLikeClick { get; set; }
    [Parameter]
    public EventCallback OnRemoveClick { get; set; }
}

In our UI code, we can see some embedded C# instructions like @foreach, @if or @onclick, this is Razor syntax. It is used for wiring up dynamic content to the static HTML. In a @code scope, we hold all the members that would go to a classic C# class. In this example, we define some component parameters. These are implemented as public class properties followed by the [Parameter] attribute.

Using components

We can easily use our components, just like any other standard HTML element.

<Croak AuthorName="Marek22@gm.com"
       Content="Blazor is really cool"
       Hashtags="@(new List<string> { "dotnet", "cs", "webdev" })"
       LikesCount="1"
       IsLiked="true"
       IsDeletable="true"/>

Since we know how to create a component, we would like to feed it with some real data. History has taught us that mixing up server interaction logic with data displays are typically a bad idea. To avoid it, we can apply a Container Pattern – Eduardo Vedes did an outstanding job explaining this concept.

To ensure a Croak component as stateless (it only displays data provided in parameters), we introduce the CroakContainer component. It provides data and takes responsibility for responding to the events which involve communication with the service layer.

@using edu_croaker.Data.Dtos
@using edu_croaker.Services
@inject CroakService CroakSrv
@namespace Components

<Croak AuthorName="@CroakData?.AuthorName"
       Content="@CroakData?.Content"
       Hashtags="@CroakData?.Hashtags"
       LikesCount="@CroakData?.LikesCount"
       IsLiked="@IsLiked"
       OnLikeClick="@LikeAsync"
       OnRemoveClick="@Remove"/>

@code {
    [Parameter]
    public CroakDto CroakData { get; set; }
    protected bool IsLiked { get; set; }

    protected async Task LikeAsync()
    {
        var likeDto = await CreateLikeDtoAsync();

        if (!IsLiked)
        {
            if (CroakSrv.LikeCroak(likeDto))
                CroakData.LikesCount++;
    	}
    	else
    	{
            if (CroakSrv.UnlikeCroak(likeDto)
                CroakData.LikesCount--;
    	}

    	IsLiked = CroakSrv.IsLiked(likeDto);
    }

    protected void Remove() { /* ... */ }
    protected async Task<LikeDto> CreateLikeDtoAsync() { /* ... */ }
    
    /* ... */
}

Razor provides fancy syntax for injecting services into our components. Croak container uses CroakService to call business logic related to liking and removing posts As you can see, we can reuse model and DTO classes directly in the client app, which makes it easier to maintain integrity and cohesion.

Razor rendering systems rely on the state of the UI. When a variable changes, all components dependent upon it re-render, according to the new state. In our example, this occurs in the LikeAsync method. Once a user presses the ‘Like’ button, we invoke appropriate service methods and change the UI state based on their response. Blazor computes visual differences and applies them selectively so that only certain components are updated.

Pages

At the top level, components are composed into pages. Each page has one or more routes specified. For instance, our Index is a default page, that’s also accessible through byHashtag or byUser routes.

@page "/"
@page "/byHashtag/{Hashtag}"
@page "/byUser/{UserName}"

@{/* UI components */}

@code {
	[Parameter]
	public string Hashtag { get; set; }
	[Parameter]
	public string UserName { get; set; }

	/* other members */
}

Building a web app

Knowing these basics lets us get started with building our first web application using Blazor. In our case, Croaker split into three layers:

  • Core – services, models, business logic
  • Infrastructure – repositories, database interaction
  • Web – client application

Components and pages were placed separately into respective directories. Web project references Core and Infrastructure modules, as all services and dependency registration performs in its Startup class. As for third-party modules, LiteDB was used for storing data, with authentication duties gracefully handled by IdentityUI. Last but not least, Bootstrap made styling our components more convenient.

The image below shows the final output.

Final thoughts

To sum up, Blazor is paving the way towards a world of front end development. If you are familiar with .NET tech stack or any modern UI framework, it will be easy for you to get up and running with Blazor. Using C# for full-stack development brings a more unified experience in building web apps. This also means that certain parts of the backend codebase are shareable with client apps.

Due to being a new technology, Blazor is still missing some features, and sometimes you may end up writing custom workarounds. Fortunately the project is under active development, and new features emerge systematically. Microsoft has laid out its bright plans for future releases, so in my opinion, it is definitely worth giving it a try.

References

Fresh software development tips delivered straight to your inbox

Subscribe to our monthly newsletter with useful information about building valuable software products.
Don't worry, we value your privacy and won't spam you with any bussines enquiries!

marek

Software Developer

I'm passionate about web and game development, and keeping things simple. I try to stop myself from proclaiming advantages of functional programming.

As part of our website we use cookies to provide you with services at the highest level, including in a manner tailored to individual needs. Using the site whithout changing the cookies settings means that they will be stored in your device. You can changes settings at any time. Accept