Get started with Blazor

Get started with Blazor

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 that 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 the option to host the app in the server as razor components or run the app in the browser on WebAssembly.

Server-side

Supports hosting Razor components on the server inside an ASP.NET core app and handles user interactions over a SignalR connection.

Blazor Server Side
Source – Microsoft Docs

Client-side

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

Blazor Client Side
Source – Microsoft Docs

Each of the models has its own benefits and downsides.  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, the however decision of one over other is not the main purpose of this post.

Get Started

New Blazor Project

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.

Select Blazor App Type

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.

Change Authentication Blazor

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

Default Blazor Home Page

Understanding the project structure

The structure of the project has some components similar to an MVC application like 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.

Blazor Solution Explorer

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.  It also contains the “DbContext” file and a model and service to get 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”.  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.  The first is to use the “Register” UI.  This will help add the user to the system.

User Registration

The 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>().  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 which helps to 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” to 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.  It can be implemented by 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

This post tried to provide an introduction of Blazor and how to create your first application with Blazor.  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 if you want to learn more about Blazor.

Leave a Reply

Close Menu
Share via
Copy link
Powered by Social Snap