facebook

Blog

Stay updated

Let’s see how to create a Single Page Application using C# instead of JavaScript
Creating a Single Page Application in C# with Blazor
Wednesday, October 23, 2019

Microsoft Developers have always had a bad relationship with JavaScript, and Microsoft has always tried to help them with its own frameworks: ASP.NET WebForms, Silverlight, Lightswitch, are probably the main examples of this. With ASP.NET MVC and .NET Core it seemed it was over, until the announcement of a new framework for the full-stack development in C#: Blazor.

Passing from a desktop to a web application, the main requirement is to return to users an experience comparable with the desktop, without refresh and with a minimum of offline support, at least until there is no need to retrieve or save data. These requirements led to the separation, in the application layer, from the backend API and a frontend Single Page Application, capable to run in the browser, that means writing it in JavaScript.

The goal of Blazor is to permit to run .NET code in the browser without the installation of a plug-in, but using the native support of the major browsers on the market for WebAssembly (https://webassembly.org/). Currently, this solution is available in pre-release and will be released on May 2020, we can try it with the download of the .NET Core 3.1 from https://dotnet.microsoft.com/download/dotnet-core/3.1, and the installation of the project template from the command line:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview1.19508.20

After the installation of the template, we can create a Blazor WebAssembly project with the command:

dotnet new blazorwasm

Now we can run the application with the classic command:

dotnet run

Opening the browser at localhost:5000 we can see the result:

But the most interesting thing is what is downloaded when we open the app:

As we can see, there are three files that make the magic possibile: blazor.webassembly.js, mono.js and mono.wasm. The mono.js and mono.wasm file are the WebAssembly version of the Mono Framework, famous for the porting of .NET specifications on non-Windows operating systems, before the arrival of .NET Core framework. The blazor.webassembly.js uses the Mono runtime to execute the .NET Code of our application in the browser, code which is in the Blazorwasm.dll file.

All code is executed in the browser: we don’t need a web server to execute the client-side part of our application. We can host the result of our publish everywhere, even on Azure Blob storage or a CDN. If we open the code of the project, we can see that the Startup.cs contains only one instruction in the Configure method:

using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
  
namespace blazorwasm
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services) {}
        public void Configure(IComponentsApplicationBuilder app)
        {
            app.AddComponent<App> ("app");
        }
    }
}

The user interface of our application will be composed of a tree of Razor components, starting from a root configured with the AddComponent extension method. A Razor component is a part of our graphic interface, that is defined in a .razor file and can contain HTML or other Razor components. If you know ASP.NET MVC the word Razor is certainly familiar: we can define the interface using a custom version of the Razor Engine.

For example, the root component App.razor contains the following structure:

<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>

This component is a composition of other components (Router, Found, NotFound, LayoutView) and a paragraph. If you have familiarity with JavaScript UI framework like Angular, this structure is very simple to understand: the Router component permits us to manage the routes in the Single Page Application and reacts if the requested component is found or not.

When we define a Razor component, we can use its name as XML element, in this case <app></app>:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title >blazorwasm </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>

Therefore, the application is composed of the classic HTML5 elements, CSS, the root Razor component and the script blazor.webassemply.js. Starting from the App root component, the whole Razor components tree will rendered.

The MainLayout component, in the Shared folder, will show the skeleton of the page, like a _Layout.cshtml or a MasterPage di ASP.NET:

@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>

In the side menu, the engine renders the Razor <NavMenu /> component, while in the main area of ​​our application it renders the @Body, which depends on the current route. How does the engine know that MainLayout is the component to use for the layout of our application? In the App component it is specified with the following line:

<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" / >

Supposing to click on the Counter menu item. The @Body will become the Counter.razor component, that is not just a component, but a page:

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

This page contains a simple button that executes C# code when clicked. The code increments a local variable, but the interesting thing is that the code is executed in the browser and it’s not JavaScript:

It’s a very interesting framework, but it’s not ready yet. Many Microsoft partners, like SyncFusion, Telerik and DevExpress are working on Razor component libraries to support the developers in the creation of applications. This happens because nowadays, another problem for a real application is the absence of a library ecosystem.

So, what we can do today? Certainly, we can start to study this technology, but we can also use a server-side version of this framework that Microsoft has released with .NET Core 3.0 in RTM. This version move the code and UI elaboration on the server and uses WebSocket with SignalR to push the interface update to the browser.

We don’t have the offline supports and we don’t use the WebAssembly browser support, but in some scenarios these are not problems, but solutions. We can run the application even on the browser that does not support WebAssembly, the download size of the application is very small, we can retrieve the data directly, without security problems because we are already on the server.

We will go in-depth with this version of Blazor in the next articles, but we can already say one thing: when both versions of Blazor will be available, we will choose between one of them based on our requirements.

Happy coding!

Written by