An Introduction to Blazor for JavaScript and ASP.NET Developers

Blazor is a new framework that lets you build interactive web UIs using C# instead of JavaScript. It is an excellent option for .NET developers looking to take their skills into web development without learning an entirely new language. But, what if you’re a JavaScript developer? Does Blazor have anything to offer you, or would you be better off sticking with Vue, React, or Angular?

We’re going to take a look at Blazor from the perspective of a JavaScript developer. We will explore the structure of a Blazor app, how it works, potential uses, and how it compares to JavaScript. Finally, we will take a tour of a simple app that demonstrates Blazor in action.

What is Blazor?

We can’t introduce Blazor without mentioning WebAssembly.

WebAssembly — or simply “wasm” — is an open specification for web browsers that was announced in 2015. It is described as a compact binary code format designed as a portable target for compilation on the web for client and server applications.

Since this announcement, some organizations have launched projects to allow high-level programming languages to run on top of WebAssembly. Microsoft took initiative, starting its Blazor project, and now you can use Blazor to run C# in client-side web apps. Thanks to the WebAssembly open standard specification, .NET code can run on browsers without plugins.

Blazor is a front-end development framework for SPAs (Single-Page Applications) that uses C# as a full-stack. You can write client-side application code with C# without relying on JavaScript as you would typically with jQuery, React, or Angular because Blazor will take the place of all of that. Coupled with ASP. NET Core server code, this means you can now have .NET end-to-end.

Blazor components are written as C# classes, then built into .NET assemblies. They are responsible for input and output operations — handling user events and rendering the UI. Components can also work as containers that are reused, shared, and distributed across multiple apps and platforms as Razor class libraries or NuGet packages. (Razor is a web development syntax that allows dynamic web page programming with HTML and C#.)

HTML pages that contain JavaScript functions to perform client-side logic are familiar to front-end developers. Similarly, a typical Blazor component is declared as a markup file (.razor extension) containing HTML elements, along with the C# code responsible for HTML rendering and event handling.

How Blazor Compares to JavaScript

Blazor provides code encapsulation through its reusable web UI components. Blazor also allows both client and server C# code to share code and libraries.

Componentization is a concept familiar to people working with React, Angular, and other JavaScript frameworks. Components are the building blocks of an app, and a typical app will have many of these. They optionally accept inputs and return HTML elements that describe how a section of the UI should appear.

ASP. NET Core provides this idea in the form of Razor components. Razor components are also the component model of Blazor. Therefore, Blazor components and Razor components are interchangeable.

Each Blazor component represents a different element in the application UI structure, such as a shopping cart, a news feed, or a comment section.

How Blazor Compares to ASP. NET Core MVC Applications

A regular ASP. NET Core MVC renders the UI as blocks of strings. Blazor, on the other hand, builds a render tree, which is not a string, but a representation of the DOM (Document Object Model) that is held in memory. Blazor keeps that representation. Any changes made to it (for instance, when a binding value is updated) will trigger a UI update for the affected DOM elements. This is a big difference from ASP. NET Core HTML Helpers and Razor Views, which render out strings.

So why does Blazor work with render trees instead of strings? Remember that Blazor code in particular (and wasm code in general) cannot access DOM elements directly. This limitation differs from ASP. NET Core HTML Helpers and Razor Views, which depend on JavaScript to get full access to the UI elements. So Blazor resorts to render trees to go back to its DOM representation, look for specific pieces of the DOM, then update them, edit, delete, and so on. The Blazor framework will listen to changes made to the data model and manipulate the render tree to apply the changes. That mechanism is what allows C# to work on the client-side.

But why should you choose to develop with Blazor rather than pure client-side JavaScript or ASP. NET Core MVC/Razor? Let’s discuss some differences between them, so you can make an informed decision before putting any effort into developing a new Blazor project.

Pros of Client-side Blazor

  1. Blazor allows .NET code to run directly in the browser. It breaks the JavaScript/Node.JS monopoly on full-stack professionals because with it, .NET developers don’t need to be programming polyglots. They can create complete solutions without writing JavaScript code.
  2. Blazor code is compiled into .NET Intermediate Language, meaning it has the potential to be faster than the equivalent JavaScript code. This compilation model can make a difference for performance-driven browser applications, such as games.
  3. You can share validation code between client and server apps. Let’s say you have form validation logic to be applied on both the browser and the back-end. With Blazor, you can create a class library in .NET Standard 2.0, and share it across client and server apps. Any change in the validation logic automatically applies to both platforms.

Cons of Client-side Blazor

  1. To run Blazor on the browser, you must not only download the application’s .wasm and .NET libraries to the browser but also Mono.wasm, the .NET runtime on top of which Blazor runs. Mono.wasm can be cached but downloading these assets for the first time will delay application startup. So even a tiny Blazor application will require downloading megabytes of code. JavaScript does not have this overhead.
  2. Blazor can’t manipulate DOM elements directly. Occasionally, your client app must have a great deal of control over the HTML elements. Since Blazor doesn’t provide this capability by itself, you must use JavaScript Interop to fill this gap.
  3. Overall client-side Blazor is currently slower than JavaScript during most aspects of running the app (not just startup). Microsoft is most definitely working to improve performance and, given their track record with performance tuning on other platforms, this should be a solved problem over time.

It’s also worth noting that, at present, there is limited debugging capability. Blazor still has to improve in this area. You can use a debugging tab in Chrome to debug and inspect the values of int, bool, and string types, and not much more than that. If you want to debug more effectively, you should put console logging throughout your client app.

The Two Faces of Blazor

We usually talk about Blazor as C# code running on top of WebAssembly on the browser, but that is only half of the story. To see the full picture, you must understand that these apps can be created to run either as Blazor client-side or Blazor server-side. When you create an app, you first choose from one of the hosting models. This configuration will drastically change the way the app works under the hood, even if the application stays the same.

Blazor client-side is the more familiar hosting model to JavaScript developers. Developers deploy the app assets to a web server, which in turn can serve client browsers with a set of static files. After the browser downloads these files, the app can run on top of WebAssembly. This behavior doesn’t differ much from client-side JavaScript apps, except for the fact that the app runs on WebAssembly instead of JavaScript.

Next, let’s talk about server-side Blazor.

A Blazor server-side app runs exclusively on the server and is built on top of ASP. NET Core SignalR, a real-time communication library based on WebSockets. Blazor server-side can run on the server on top of the full ASP. NET Core web framework, without the limitations imposed by WebAssembly when apps run on the browser.

Current Blazor Tools and Support

When Microsoft started Blazor, it was an experimental framework for .NET single-page apps that could run on the browser. But Microsoft is committing to ship it as a supported web UI framework. It is supported on Windows, Linux, and Mac OS, and is distributed by Microsoft as a feature of ASP. NET, the company’s flagship for web development. The ASP. NET Core pipeline now includes Blazor in its official rollout.

Creating a Sample Blazor App

Ready for a hands-on? To understand more clearly how Blazor works, follow these steps:

Install the latest .NET Core 3.0 Preview SDK release.

Install the Blazor templates by running the following command in a command shell:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview9.19424.4

Install Visual Studio Code and the latest C# for Visual Studio Code extension or install Visual Studio 2019 Preview.

The most basic form of Blazor requires only the client project. But since we want a client-side experience with a server-side back-end project, execute the following command in a command shell:

dotnet new blazorwasm -o BlazorClientServer --hosted

Open the BlazorClientServer.sln solution in Visual Studio, or open the BlazorClientServer folder in Visual Studio Code.

Run the solution.

In a browser, navigate to https://localhost:5001

Here we see the application home page.

Now, navigate to the other two menu items, Counter and Fetch data:

This looks a lot like a regular ASP. NET Core MVC website. You can think of a Blazor solution as a new flavor of ASP. NET Core that replaces JavaScript with C# code, as we are about to see.

Now let’s take a close look at the projects contained in the solution generated earlier:

The BlazorClientServer.Client is a project written in .NET Standard 2.0. It is the SPA that contains the Blazor pages and components that run inside a browser and does not require page reloading during use.

BlazorClientServer.Server is an ASP. NET Core project for HTTP API services. It holds the controller and action intended to return weather forecast data as requested by the browser.

BlazorClientServer.Shared is a .NET Standard 2.0 project that contains the WeatherForecast class, which is used in both client and server projects.

When you execute the application, the BlazorServer.Client.dll assembly is compiled and deployed to localhost, but the web server doesn’t run it. Instead, localhost waits for the browser to request this file. Upon download, this assembly will run locally in the browser as a WebAssembly.

But when does the browser download this file? If you look at index.html, you see that it doesn’t reference BlazorServer.Client.dll. Instead, it specifies the URL for blazor.webassembly.js:

<!DOCTYPE html><html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><title>BlazorClientServer</title><base href="/" /><link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /><link href="css/site.css" rel="stylesheet" /></head><body><app>Loading...</app><script src="_framework/blazor.webassembly.js"></script></body></html>

But wait — we said Blazor doesn’t require JavaScript, right? That’s true. Still, the blazor.webassembly.js file is needed to download the Mono.wasm runtime, the .NET DLLs, and the application DLLs. When these assets are downloaded, the application is ready to run as a WebAssembly.

The top elements in the Blazor component tree are defined in the App.razor file. The Router component below, which is provided by the Blazor template, sets the default layout to MainLayout:

<Router AppAssembly="@typeof(Program).Assembly"><Found Context="routeData"><RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /></Found><NotFound><LayoutView Layout="@typeof(MainLayout)"><p>Sorry, there's nothing at this address.</p></LayoutView></NotFound></Router>

What we see above is a structure made of components like the one you would expect from a component-based framework such as React, Angular,or Vue.JS. Each component is defined in a separated .razor file.

The MainLayout component, in turn, defines the layout structure in plain HTML code with CSS classes. The application layout is displayed as a sidebar menu and a central page body:

@inherits LayoutComponentBase<div class="sidebar"><NavMenu /></div><div class="main"><div class="top-row px-4"><a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a></div><div class="content px-4">@Body</div></div>

Note that the MainLayout component above inherits from another LayoutComponentBase. What does that mean? Inheritance gives a component the ability to build upon a more basic component. It reduces code duplication and simplifies app development. The body is a RenderFragment to be rendered inside the layout.

public abstract class LayoutComponentBase : ComponentBase{protected LayoutComponentBase();//// Summary://     Gets the content to be rendered inside the layout.[Parameter]public RenderFragment Body { get; set; }}

Besides components that render parts of the user interface, Blazor also has the concept of pages, like any ordinary HTML application. Here, we can see a simple page with a counter and an IncrementCount button.

@page "/counter"<h1>Counter</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {int currentCount = 0;void IncrementCount(){currentCount++;}}

But how does this page differ from a regular HTML page?

In the first line, you can see a page directive: @page “/counter”. It not only declares the file to be treated as a page, but also defines that this page should be rendered whenever the “/counter” route is requested by the user.

The @currentCount defines a binding expression that simply renders the currentCount variable inside the HTML. And @onclick is an event callback that triggers the IncrementCount when the button is pressed.

But how does this Blazor client-side app interact with a server backend? Let’s investigate the FetchData.razor page to find out.

@page "/fetchdata"@using BlazorClientServer.Shared@inject HttpClient Http<h1>Weather forecast</h1><p>This component demonstrates fetching data from the server.</p>@if (forecasts == null){<p><em>Loading...</em></p>}else{<table class="table"><thead><tr><th>Date</th><th>Temp. (C)</th><th>Temp. (F)</th><th>Summary</th></tr></thead><tbody>@foreach (var forecast in forecasts){<tr><td>@forecast.Date.ToShortDateString()</td><td>@forecast.TemperatureC</td><td>@forecast.TemperatureF</td><td>@forecast.Summary</td></tr>}</tbody></table>}@code {WeatherForecast[] forecasts;protected override async Task OnInitializedAsync(){forecasts = await Http.GetJsonAsync<WeatherForecast[]>("WeatherForecast");}}

When initialized, the FetchData page retrieves weather forecast data asynchronously through an HTTP GET request. Usually, JavaScript would implement this requirement as an AJAX function. Here, this role is taken by the Http.GetJsonAsync() method.

The back-end application (the BlazorClientServerApp.Server project) doesn’t do much. It just hosts the server application at localhost and provides the server endpoint implementation for the weather forecast function.

And here’s the weather forecast function itself, WeatherForecastController.cs.

[ApiController][Route("[controller]")]public class WeatherForecastController : ControllerBase{//code block removed for the sake of brevity//...[HttpGet]public IEnumerable<WeatherForecast> Get(){var rng = new Random();return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20, 55),Summary = Summaries[rng.Next(Summaries.Length)]}).ToArray();}}

Finally, we have the BlazorClientServerApp.Shared project, which contains just the WeatherForecast class. This doesn’t seem to be too important, but this same class can run on the browser, via WebAssembly, or on the server, inside the full ASP. NET Core application.

Blazor implements .NET Standard 2.0, a specification of APIs shared between different .NET implementations. .NET Standard class libraries can be distributed across different platforms, including Blazor, .NET Framework, .NET Core, Xamarin, and Mono.

The WeatherForecast class is pretty simple:

public class WeatherForecast{public DateTime Date { get; set; }public int TemperatureC { get; set; }public string Summary { get; set; }public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);}

Blazor and Your JavaScript Apps: What’s Next?

In this article, we introduced Blazor and the concept of WebAssembly and discussed how this framework compares to traditional JavaScript and ASP. NET programming.

We saw how the same application works differently depending on whether it uses client-side or server-side hosting, weighing up the pros and cons of the Blazor client-side approach.

Finally, we took a guided tour around different parts of a sample Blazor client-server app to show it in action, pointing out where it differs from a JavaScript application.

While Blazor is exciting, it has much room for improvement, especially in tooling and debugging. JavaScript programming is alive and well and will remain as such for a long, long time. But WebAssembly is a technology that front-end developers can’t ignore for too long. Blazor is an excellent opportunity for .NET professionals to take advantage of this new framework and become full-stack developers without having to learn a new language.


by Marcelo Ricardo de Oliveira

Originally published at https://www.grapecity.com on October 29, 2019.

GrapeCity Developer Solutions

Written by

We provide developers with the widest range of Microsoft Visual Studio components, IDE platform development tools, and applications.

GrapeCity

GrapeCity

Sharing stories, podcasts, concepts, and code.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade