You are currently viewing 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. 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.

Blazor Server Side
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.

Blazor Client Side
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

New Blazor Project

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.

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

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

User Registration

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("[email protected]");

    if (user == null)
    {
        user = new IdentityUser()
        {
            UserName = "[email protected]",
            Email = "[email protected]",
        };
        await UserManager.CreateAsync(user, "Test@579");
    }
    await UserManager.AddToRoleAsync(user, "Admin");


    IdentityUser user1 = await UserManager.FindByEmailAsync("[email protected]");

    if (user1 == null)
    {
        user1 = new IdentityUser()
        {
            UserName = "[email protected]",
            Email = "[email protected]",
        };
        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

Recommended Courses

We may receive a commission for purchases made through these links.

Further reading

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

This Post Has 4 Comments

  1. Kaushik Roy Chowdhury

    The method CreateUserAndRoles(IServiceProvider serviceProvider) has severe restrictions as I found trying many combinations to add more users in User or Admin roles but it fails always with the Foreign Key violation errors:
    KEY Constraint “FK_AspNetUserRoles_AspNetUsers_UserId. The conflict occurred in the database …………… table
    “dbo.AspNetUsers”
    I also created a Manager role and tries to add an user to it but failed with the above error.
    I looked through the table data’s in an effort to resolve the issue but in vain

    It though worked as it was without changes. Any Ideas why?

    Thanks

    1. Kaushik Roy Chowdhury

      Please ignore my comments above. I have sorted it out at my end with a slight variation. Thanks for the article.

  2. Bart

    How is the CreateUserAndRoles method call from the Config method in Startup?
    ie what is the correct service provider?

  3. Barto

    Sorry found out already from your github
    CreateUserAndRoles(serviceProvider).Wait();

Leave a Reply