Introduction

C#, one of the most popular programming languages, is primarily used for back-end development. But in today’s world, industry’s standards have changed, meaning that full-stack developers are more sought after than their front or back-only counterparts.

As a consequence, C# developers ought to learn a front-end language (like JavaScript) in order to remain competitive on the market. Since the release of ASP .NET back in 2002, Microsoft has been trying to make it compelling for C# developers to do web development.

One of the major breakthroughs happened in 2010 with the release of ASP .NET MVC 3 which included Razor, a fresh new syntax which allowed blending either C# or VB with HTML code. Add HTML5 (2014) into the mix and you’ve got a plethora of web applications written in pure C#, HTML, and CSS.

Nowadays, 9 years since the release of Razor and almost 23 since ASP classic first emerged, it has been reached what is considered to be the holy grail of .NET development: C# code running in the browser – that is, without any plugins or add-ons to install (no, this is not yet another Silverlight).

Ladies and gentlemen, please welcome Blazor, the new and hot Web Development Framework created by the ASP team that enable C# developers to build beautiful SPA applications with minimum knowledge of HTML and CSS.

First released in March 2018, Blazor, whose name derives from a combination of the words Browser and Razor, comes in two flavors. While the server-side (aka Razor Components) made its way into the .NET Core 3.0, the client-side has remained experimental (mainly because the WebAssembly runtime needs some polishing).

Now that we’ve got a brief idea of what Blazor is, let’s see it in action. We’ll begin talking about Components, then about how Dependency Injection is achieved, discussing Routing afterward and end with JavaScript interoperability. But first, let’s talk about prerequisites.

To be able to create and run Blazor applications (and the code snippets), you will need to install Visual Studio 2019, .NET Core 3.0 and the Blazor Language Services extension (available at the Visual Studio marketplace).

Components

Components are the building blocks of a Blazor application. Being stored in a .razor file, they comprise two parts: HTML and C# code. These two are linked by Razor directives, which all begin with the “@” symbol. Here is an example:

<b>@Message</b>
@functions { 
    const string Message = "Hello, World!"; 
}

In this example, we are displaying the text “Hello, World!” in bold. The separation between HTML and C# code is done with the help of the Razor directive “@functions”. Here, the message is hardcoded into a constant. But what if we wanted to be able to change the message as often as we wanted? Nothing easier than clicking a button!

<input bind=”@UserInput” placeholder=”Enter your text here” />
<button onclick=”@SetMessage”>Click Me!</button>
<h1>@Message</h1>
@functions {
    string UserInput { get; set; }
    string Message { get; set; }
    void SetMessage() => Message = UserInput;
}

This example is about allowing the user to type something into a text box and then mirror it one line below. First, we declare a string variable inside our functions block, then we bind it to the text box using the bind property of the input element. Then, we create a method that assigns the input text to the Message variable, which is then printed inside a header tag.

Nesting

Blazor components support nesting i.e. a component can contain one or more multiple, which in their turn can contain one or more components and so on.

Index.razor: <HelloWorld/>
HelloWorld.razor: <h1>Hello, World!</h1>

Here, the Index component (which is the default component) contains just a reference to the HelloWorld component, which in turn contains some text.

Component Parameters

Components can also contain parameters, which enable one component to provide values for another’s component parameter.

Index.cshtml: <HelloWorld Message="Hello, World!"/>
HelloWorld.cshtml:
@using Microsoft.AspNetCore.Components
<h1>@Message</h1>
@functions {
    [Parameter] string Message { get; set; }
}

This example displays how the Index component provides a value for the parameter Message, which belongs to the HelloWorld component. Note the @using directive that is required for the Parameter annotation.

Loop and Control Structures

Although this article is not about the Razor syntax itself, one may find useful to recall the use of loops and control structures. We’ll exemplify the ForEach and Switch structures, leaving the others (if-else, while, do-while, for) to be tried out by the reader.

@foreach (var character in "Hello, World!") {
    switch (GetState(character)) {
        case State.Vowel: <h3>@($"{character} is a vowel!")</h3> break;
        case State.Other: <h3>@($"{character} is not a vowel!")</h3> break;
        default: <h3>@($"{character} is unknown!")</h3> break;
    }
}
@functions {
    enum State { Vowel, Other };
    const string Vowels = "AEIOU";
    static State GetState(char c) => Vowels.Contains(char.ToUpper(c)) ? State.Vowel : State.Other;
}

Dependency Injection

In Blazor, dependency injection can be achieved using the @inject directive. There are many services pre-baked into the Blazor runtime and one of the most popular is HttpClient, which supports basic HTTP operations.

@inject HttpClient HttpClient
<button onclick=”@GetExchangeRate”>Get GBP/USD Exchange Rate</button>
<h1>@ExchangeRateInfo</h1>
@functions{
    string ExchangeRateInfo { get; set; }
    const string Uri = “https://api.exchangeratesapi.io/latest?base=GBP&symbols=USD”;
    async Task GetExchangeRate() => ExchangeRateInfo = await HttpClient.GetStringAsync(Uri);
}

In this example, we are sending a GET request to the ECB (European Central Bank) API Service to get (among other information) the latest exchange rate for GBP/EUR. Note that all the methods supported by the HttpClient are asynchronous. Also, note that there is no difference between calling async and non-async methods.

Another useful method is GetJsonAsync<T>, which take can the response directly into an object.

@page "/"
@using Microsoft.AspNetCore.Components
@inject HttpClient HttpClient
<button onclick="@GetSomeData">Click Me!</button>
<div class="card">
    <div class="card-body">
        <h1 class="card-title">@UserName</h1>
        <h2 class="card-text">@UserEmail</h2>
    </div>
</div>
@functions{
    string UserName { get; set; }
    string UserEmail { get; set; }
    const string Uri = "https://jsonplaceholder.typicode.com/users/1";
    async Task GetSomeData() {
        var user = await HttpClient.GetJsonAsync<User>(Uri);
        UserName = user.Name;
        UserEmail = user.Email;
    }
}
public class User {
    public string Name { get; set; }
    public string Email { get; set; }
}

Routing

Blazor applications contain a special directive for routing – @page, which must be followed by a string describing the location of the page relative to the root page. Thus, the @page “/” directive marks the current component as being the root one (that is, the landing page), while @page “/helloworld” denotes a custom component contained in the helloworld.cshtml file.

@page "/helloworld"
<h1>Hello, World!</h1>

Parameters

Routes also support parameters – it is possible to pass a parameter to a component directly though it’s Uri.

@page "/helloworld/{Message}"
<h1>@Message</h1>
@functions {
    [Parameter] string Message { get; set; }
}

Navigating to http://localhost will cause the message SomewhereOverTheRainbow to be displayed.

Navigating with UriHelper

Furthermore, it is possible to redirect a component to another one by using the UriHelper service.

@inject IUriHelper UriHelper
<button onclick="@FlyOverTheRainbow">Take Me To Paradise</button>
@functions{
    void FlyOverTheRainbow() => UriHelper.NavigateTo("/helloworld/WelcomeToParadise!");
}

Javascript interoperability

Finally, in this section, we are going to talk about how can JavaScript code can be called from a C# method. But first, it is worth mentioning that most Web API’s work out of the box (consider the list provided by Mozilla). For example, calling window.alert()  works just as expected (displays an alert with a given message). Going back to interoperability, it is necessary to first register the JS function inside a regular Script tag, under the body section of the file index.html.

<script>
    GetMessage = () => {
        return "Hello, World!";
    }
</script>

Next, we can invoke the JavaScript function by calling its name using the current JS Runtime provided by Blazor:

<h1>@Message</h1>
@functions {
    string Message { get; set; }
    protected override async Task OnInitAsync() =>
        Message = await JSRuntime.Current.InvokeAsync<string>("GetMessage");  
}

That’s it! Note the asynchronous method InvokeAsync, which takes a generic type parameter. In our case, it’s a string. Calling C# methods from JavaScript is also possible, though I’d rather let the reader explore further usages of this scenario.

Final words

I hope you’ve enjoyed reading about Blazor as much as I’ve enjoyed writing it. If I stirred up your interest even just a little, go ahead and try it, you won’t regret!