Blazor is a new web UI framework based on C#, Razor, and HTML. This runs in the browser via WebAssembly. It helps build interactive web UI using C# instead of JavaScript. This post demonstrates how to build a SPA using Blazor. Blazor simplifies the task of building fast and beautiful SPAs that run in any browser. It does this by enabling developers to write Dotnet based web apps. These apps run client-side in web browsers using open web standards. Let’s get started with Blazor.

In this post, we will discuss the following

Hosting Models

Enable Authentication and Authorization

Dive deep into Default Blazor pages

Prerequisites

Visual Studio 2019

Install .NET Core 3.0

Install Blazor Templates

Hosting models

You have two options to host the app. First, in the server as razor components. Next is run the app in the browser as Web Assembly.

Server-side

Supports hosting Razor components on the server inside an ASP.NET core app. User Interactions will be handled over a SignalR connection.

Source – Microsoft Docs

Client-side

The Blazor app along with the .NET runtime and other dependencies downloaded to the browser. Additionally, you can share the model, validation and other business logic between client and server-side. Moreover, you can also take advantage of several libraries that will run directly in .NET on the browser.

Source – Microsoft Docs

Obviously, each of the models has its own benefits and downsides. Particularly, most of them are related to dependency, performance, browser compatibility, etc. The decision of choosing one of the approaches for implementation is up to you. We will discuss server-side hosting with an example in this post. However, the decision of one over the other is not the main purpose of this post.

Get Started

First, search for “Blazor” when creating the new project and select “Blazor App”.

On the next page, select the type of app you want to create. I am going to create a “Blazor Server App” for the purpose of this post.

Before creating the project, click the “Change” link under the “Authentication” section. Select “Store user accounts in-app”. This option lets us use a local user accounts store for authentication. Other options available are No Authentication, Work or School Accounts and Windows Authentication. You can disable the HTTPS from the properties page (Debug tab) of the project later.

Now we have created the project with authentication enabled. When you run the project, you can see the following screen.

Understanding the project structure

The structure of the project has some components similar to an MVC application. You can see Areas, appsettings.json, Program.cs, and Startup.cs. In addition to that, you can also see files with razor extension and they are specific to “Blazor”. Let’s talk about them in detail.

Identity – This folder was created because we have selected an authentication methodology while creating the project. It has an “AuthenticationStateProvider” class and HTML files for Login and Logout.

Data – Nuget packages related to Entity Framework are available by default while creating the project. This folder contains a migration file to create tables related to authentication like Users, Roles, etc. Along with this, it also contains the “DbContext” file, a model and service. The service gets the weather forecast details for the default demo page.

Pages – If you are a .NET developer, you may already hear about the razor. Blazor apps are based on components. Components are reusable building blocks. It can be an individual control or a block with multiple controls. These component classes are written in razor markup. However, the main difference of razor in the context Blazor is, it is built around UI logic and not on request/response delivery.

Enable Authentication and Authorization

To enable the authentication, do the following steps

Create the tables to store user and role details

Add User and Roles

Implement authorization

Create tables

Run the Entity Framework’s “update-database” command to trigger the table creation. By default, the application creates the database in “localdb”. Alternatively, you can modify the connection string in appsettings.json if required. The default migration creates tables related to authentication like AspNetUsers, AspNetRoles, etc.

User Registration

You can add users to the application in two ways. First option is to use the “Register” UI. This will help add the user to the system.

Next option is to seed the User and Role data from “Startup.cs”. Role services are not added by default but can be added with AddRoles<TRole>(). Importantly, you have to modify the “ConfigureServices” method to enable Roles.

public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<IdentityUser>() .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddRazorPages(); services.AddServerSideBlazor(); services.AddScoped<AuthenticationStateProvider, RevalidatingAuthenticationStateProvider<IdentityUser>>(); services.AddSingleton<WeatherForecastService>(); }

I use the following method to seed both Roles and Users in the Identity tables. The method is called inside the “Configure” method of “Startup.cs”. It uses RoleManager and UserManager to check and add Roles and Users.

private async Task CreateUserAndRoles(IServiceProvider serviceProvider) { //initializing custom roles var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>(); var UserManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>(); string[] roleNames = { "Admin", "User" }; IdentityResult roleResult; foreach (var roleName in roleNames) { var roleExist = await RoleManager.RoleExistsAsync(roleName); if (!roleExist) { //create the roles and seed them to the database: Question 1 roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName)); } } IdentityUser user = await UserManager.FindByEmailAsync("admin@blogofpi.com"); if (user == null) { user = new IdentityUser() { UserName = "admin@blogofpi.com", Email = "admin@blogofpi.com", }; await UserManager.CreateAsync(user, "Test@579"); } await UserManager.AddToRoleAsync(user, "Admin"); IdentityUser user1 = await UserManager.FindByEmailAsync("jane.doe@blogofpi.com"); if (user1 == null) { user1 = new IdentityUser() { UserName = "jane.doe@blogofpi.com", Email = "jane.doe@blogofpi.com", }; await UserManager.CreateAsync(user1, "Test@246"); } await UserManager.AddToRoleAsync(user1, "User"); }

Implement Authorization

Now we have created the tables, add users and roles. Let’s enable authorization to pages. Blazor has an “AuthorizeView” component for authorization purposes. This component helps display content depending on the authorization status. If you have the page content inside “AuthorizeView”, only an authorized user can see it.

<AuthorizeView> <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> </AuthorizeView>

What if you need to show different content for authorized and unauthorized users? You can use “Authorized” and “NotAuthorized” elements inside “AuthorizeView”. This helps serve different content based on the authorization status.

<AuthorizeView> <Authorized> <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> </Authorized> <NotAuthorized> You are not authorized to view this page! </NotAuthorized> </AuthorizeView>

You can authorize users based on Role or Policy. To implement that you have to mention the Policy and Roles as attributes inside the “AuthorizeView” element. You can also use the “Authorize” attribute. The name of the roles and policy mentioned inside AuthorizeView is case sensitive.

<AuthorizeView Roles="Admin"> <Authorized> <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> </Authorized> <NotAuthorized> You are not authorized to view this page! </NotAuthorized> </AuthorizeView>

Dive deep into Blazor Pages

Let’s analyze a razor component and try to understand the basic building blocks of it. I am going to use “FetchData.razor” for this.

@page "/fetchdata" @using BlazorServerApp.Data @inject WeatherForecastService ForecastService <h1>Weather forecast</h1> <p>This component demonstrates fetching data from a service.</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 ForecastService.GetForecastAsync(DateTime.Now); } }

@page – The route attribute in a component is set using “@page” attribute. This specifies that the component is a routing endpoint. A component can have multiple route attributes by having multiple “@page” directives.

@inject – You can inject the services into the component using the “@inject” attribute. In the example, “WeatherForecastService” is injected and later used to retrieve the data. You can use the services from registering them in “Startup.cs” also similar to ASP.NET MVC.

@code – This block contains the code for rendering and event handling. It can be anything like variable declarations to methods. There is something similar to “@code” which is “@functions” and used for the same purpose. From ASP.NET Core 3.0, it is suggested to use “@code” instead of “@function”.

Summary

In short, this post tried to provide an introduction of Blazor and how to create your first application with Blazor. In addition to that, we also discussed the hosting models, implementation of authentication, authorization and the directives used in the default pages.

The full implementation of this post will be available in Github

Next up

Watch this for more posts on Blazor. Some of the posts I am planning to write are

CRUD using EF Core with Modal dialogs

Validation in Blazor

Containerization of a Blazor app

Routing with Blazor

Further reading

The following are some of the links you can refer to if you want to learn more about Blazor.