Blazor is a new Microsoft framework for building single page web applications using C# rather than JavaScript-based frameworks such as Angular and React. The basic building block of a Blazor app is a component created with C#, HTML, and CSS. Since the client-side and server-side code can both be written in C#, code can easily be shared and reused. Just like in an MVC application, Razor syntax is used to combine C# code with HTML. Blazor takes this one step further and lets you create dynamic web pages running either in the browser (through WebAssembly) or running on the server and sending updates to the client (through SignalR).
Why Use Blazor?
The biggest question with any new technology is if it is worthwhile to use in your project, especially in a fast-moving environment like web development where tried and true frameworks already exist. As mentioned previously, using C# for your client application means that your libraries can be shared between your server and client-side projects. No more maintaining duplicate models or rewriting the same logic across two different languages. If you have an API written in C#, then it is likely you already have some parts of your code base that will be useful in getting a web application off the ground. Additionally, if you have worked with Angular apps in the past, some of the concepts and interfaces within Blazor apps will be familiar.
Depending on your situation, Blazor offers two models: WebAssembly and Server. In the server model, the server is responsible for rendering the components. When visiting the page, the client browser is sent a small file that uses SignalR to communicate with the server. The browser will send the server any events that occur, and the server will send back changes to the page. In this case, the browser has much less work it needs to do and will be less performance intensive on the user’s computer. However, since all the interaction is network based, a poor connection or an overwhelmed server can cause visible delays to the clients.
In the WebAssembly version, everything runs directly in the browser. Code is compiled like any other .NET application. The difference is that those files are then sent to the browser along with a WebAssembly version of the .NET runtime – there is no required server infrastructure. When a Blazor WebAssembly project is compiled, the result is a folder of files that make up a static website. The collection of files can be hosted anywhere that can serve static websites, such as an Amazon S3 bucket. There is no need to stand up a server or spin up an instance in Azure for the purpose of serving the application. While this does require more work from the client’s machine, it offers additional flexibility in how the application is hosted and utilized. In fact, Blazor WebAssembly applications can be set up as a progressive web app, allowing them to behave like a desktop application and enabling features like offline use, push notifications, and automatic background updates. This blog post will walk through an example of a Blazor WebAssembly project.
What is WebAssembly?
WebAssembly is a low-level programming language understood by modern web browsers. Like assembly, the language understood by the processor inside a computer, and other programming languages are transformed into this language when the program is compiled. If a WebAssembly compiler exists for your favorite programming language, you can opt to use that language for the code that will run in the client browser. All APIs that are accessible by JavaScript are also available to WebAssembly. Additionally, JavaScript code can be called from within the WebAssembly sandbox so there is no need to worry about rewriting or finding replacements for libraries your code relies on. For more in-depth information about WebAssembly, visit the homepage here.
Project Structure
Recent versions of Visual Studio 2019 come with templates for both WebAssembly and server-side Blazor applications. When you create a new solution with the WebAssembly template, the base project will contain a sample application to show off some of the basic concepts of Blazor.

Like other .NET web apps, Program.cs is the entry point to the application. Components that your application will route to, or have a URL for, go in the Pages folder. Reusable components that will be on multiple pages, rather than a page itself, will go inside the Shared folder. The wwwroot folder holds your CSS files, images, and index.html file. For each request to the app, the index.html file is rendered. This specifies the root element “App” where the application will be inserted into the page. The root element can be defined in Program.cs.


Interacting with the Page
Let’s look at one of the pages included within the default app, the counter page. This page is an example of using C# for basic client-side logic to handle an event and updating the HTML accordingly. When first loaded, the current count will read 0. Each time the button is clicked, the number will increase by 1.

If we were to create this page using JavaScript (with or without JQuery), we would need to do a few things:
- Keep a variable to store the number of times the button has been clicked
- Get a reference to the button element and the paragraph element used to display the current count
- Add an event handler to the button with a callback function to increase the counter variable
- Update the text within the paragraph element with the current value of the counter
What does this look like within a Blazor component?

Looking at the code segment, we can clearly see the C# variable and function for handling the counter. However, with Blazor, we do not need to manually define event handlers – we can leverage attributes directly in HTML elements, and we can bind the variables to the page, and the rest is taken care of. Rather than writing JavaScript to find the element and calling “addEventListener”, we can use Razor syntax to create an attribute on the button element with the name “onclick” and provide the name of the C# function. The “@” symbol before onclick lets the compiler know that we are using C# instead of HTML. Similarly, we can access the value stored within the variable by using the “@” symbol as well. The page will automatically update as the variable changes.
Blazor takes this one step further and lets you create dynamic web pages running either in the browser (through WebAssembly) or running on the server and sending updates to the client (through SignalR).
A minor detail on the component is the first line: @page “/counter.” This is found on full page components (not on the components that are designed to be nested in a page) and declares the route that will bring this component up. In this case, adding “/counter” to the root of the website address pulls up the counter page.
Injecting Services and Calling an API
The Counter page shows us how to interact with the user interface, respond to events, and perform some simple logic all in the client’s browser. In a real application, however, it is rare for a page not to require some sort of outside information. Since we are working with a WebAssembly project, this data will likely be retrieved through a call to an API. To use a service such as an HTTP client from within a component, the service needs to be registered at startup and then injected into the components that wish to use it. The weather forecast page in the demo app uses an injected service to retrieve weather information as JSON data and creates a table with that information.


First off, let’s look at the HTML for this page:

If the list “forecasts” is null, the text “Loading” will appear (as seen in the first image). Otherwise, a table will be created with a row for each individual forecast in the list. At the top, we again have the @page directive to specify the route for this page. The line below that is the directive used for injecting a service into a component so it can be referenced from within the component’s code block. In this case, we are injecting an instance of the HttpClient class and naming it HTTP.

The C# section of the weather forecasts page defines the WeatherForecast class and creates a variable to hold an array of WeatherForecasts. This component overrides a function called OnInitializedAsync to make the request for weather data using the HttpClient object we injected earlier. OnInitializedAsync is called when the component is ready to start. By overriding it, we can add additional logic that, once completed, will cause the component to refresh. This is how the page originally shows “Loading” but switches to showing a table once the call to GetJsonAsync is completed and returns data.
To inject a service, register it as a dependency in Program.cs. The HttpClient class has its own method for registering it, but generic functions exist to allow you to add your own classes to the collection of injectable services.

Working with JavaScript
Despite being able to write client-side logic in C#, there may be situations where you need to use existing JavaScript code. Blazor provides the ability to call JavaScript functions from your C# code through the JavaScript interoperability service. It is injected into a component like the HttpClient in the previous section, but it is registered by default and does not require any modifications to Program.cs. First, start by including the JavaScript you want to call. This can be a separate file that is referenced or included directly in index.html.

Next, inject the JSRuntime into your component. We will be modifying the counter page, so we will add this to the top of counter.razor.

Then, update the IncrementCount function in the component:

As long as the arguments and the return type can be serialized into JSON, the interop library will support passing to and from .NET and JavaScript.
The new IncrementCount leverages two functions from the JSRuntime: InvokeAsync and InvokeVoidAsync. For both InvokeAsync and InvokeVoidAsync, the first argument is the name of the function to be called, and the second argument is any arguments that you want to pass to the JavaScript function. Both functions will call into JavaScript code, but we must use InvokeAsync to get a return value. As long as the arguments and the return type can be serialized into JSON, the interop library will support passing to and from .NET and JavaScript. In the updated version of IncrementCount, InvokeAsync is called first in order to call the JavaScript function askForName and it expects a string to be returned. Then, InvokeVoidAsync is used to call showMessage and passes in a string that uses the currentCount as well as the name the user entered into the prompt.
Conclusion

Blazor is a new technology that has quickly grown in popularity. It is something that feels familiar to web developers who have worked in the .NET ecosystem or have used frameworks like Angular. Being able to use all your existing C# code from within the browser and leverage the strengths of WebAssembly is an exciting prospect that will lead to new and interesting solutions for web-based applications.
Tallan is well versed in several aspects of web development. To get started with a project or learn more about our solutions, click here.