Special Offer: My C#/.NET Bootcamp Course is out now. Get 10% OFF using the code FRIENDS10.

This video is part of The FREE Blazor Crash Course. In this crash course, we build an actual Blazor WebAssembly application based on .NET 5.

Table of Content

  1. The FREE Blazor Crash Course – Getting Started
  2. Blazor Form Component & Validation
  3. Blazor API Handling
  4. Blazor Modal Dialog Component
  5. Blazor CSS Handling
  6. Static Images
  7. Building a Dashboard (this article)
  8. End-to-End Testing using SpecFlow

In this video, we will integrate a third-party user interface library. We will then use that library to build a Dashboard for the FinanceMentor application.

This time, we build a Dashboard for the FinanceMentor application.

The Dashboard We’re Going to Build

The first row contains a bar chart with bars for every month in 2021. We compare the sum of the earnings to the sum of the expenses.

Blazor App: Completed Dashboard

Blazor App: Completed Dashboard

In the second row, we have a more detailed view of all the earnings in the last three months grouped by its category and displayed using a pie chart.

The third row also contains a pie chart of all the expenses in the last three months grouped by its category.

The Radzen User Interface Library

Let’s start by looking at the library we are going to integrate into the FinanceMentor application. 

Radzen is a company that develops user interface libraries. They also have an open-source Blazor components library with more than 60 native controls. The library is open source, and we can even use it in commercial projects for FREE.

What’s interesting to us developers is that we can use the same library for server-side and client-side Blazor.

Let’s take a look at the components we will use in this video. We will use charts from the Radzen library. To be specific, we will use the Column Chart and the Pie Chart components.

Radzen does not sponsor this video, but so far, I had a great experience using this library and therefore want to spread the word about it. You can find the Radzen Blazor Components Library at blazor.radzen.com.

Integrating the Radzen User Interface Library

Now that we are convinced that we want to use the Radzen Blazor components library in our FinanceMentor application, we need to install the Nuget package.

Open the NuGet Package Manager for the FinanceMentor.Client project. In the Browser tab, we search for Radzen.Blazor. We install the latest stable version. At the time of this recording, it’s version 3.2.0.

Next, we open the _Imports.razor file and add the Radzen and Radzen.Blazor namespaces to it. Namespaces added to this file become available to all components in our Blazor application.

@using Radzen
@using Radzen.Blazor

Next, we open the index.html file and add a reference to the Radzen stylesheet.

<link href="_content/Radzen.Blazor/css/default.css" rel="stylesheet" />

The _content part of the address is Blazor-specific. It specifies that the desired file is part of the Radzen.Blazor NuGet package.

We are almost ready, but before we can implement the first component using the Radzen Blazor library, we also need to add a reference to a JavaScript file. Below the script tag for the blazor.webassembly.js file, we add another line to load the Radzen.Blazor.js file.

<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>

Use the Radzen.Blazor Library

Now that we installed the library let’s see if it works. We open the Index.razor file and use the RadzenButton component.

<RadzenButton Text="Clicke me!"></RadzenButton>

Let’s build and start the application.

We can see the beautiful RadzenButton on the index page of the FinanceMentor application.

Cleaning up the Index Page

Before we start building the Dashboard, let’s clean up the Index page. 

We remove the RadzenButton we added before, and we also remove the SurveyPrompt component that was generated as part of the project template. We can also remove the SurveyPrompt.razor file in the Solution Explorer.

Define the IDataService Interface

Before we can implement the charts, we need to implement a data service that returns the data in a structured way. For simplicity reasons, I put it all in the same service.

Let’s start by creating a new folder in the client project and name it Services. Next, we create a new interface and name it IDataService. I paste a snippet for the interface definition that defines a method to load data for the last three months and the year for both the expenses and the earnings.

using System.Collections.Generic;
using System.Threading.Tasks;

namespace FinanceMentor.Client.Services
{
    public interface IDataService
    {
        Task<ICollection<YearlyItem>> LoadCurrentYearExpenses();
        Task<ICollection<YearlyItem>> LoadCurrentYearEarnings();
        Task<ThreeMonthsData> LoadLast3MonthsExpenses();
        Task<ThreeMonthsData> LoadLast3MonthsEarnings();
    }
}

Next, we create the data types we used in the IDataService interface definition. Let’s create a new class in the Service folder and name it YearlyItem.

namespace FinanceMentor.Client.Services
{
    public class YearlyItem
    {
        public string Month { get; set; }
        public decimal Amount { get; set; }
    }
}

The YearlyItem data class contains two properties. We define a string Month property and a decimal Amount property.

Next, we create a new class and name it ThreeMonthsData. We create three properties of the MonthlyData type and name them CurrentMonth, LastMonth, and PreviousMonth.

namespace FinanceMentor.Client.Services
{
    public class ThreeMonthsData
    {
        public MonthlyData CurrentMonth { get; set; }
        public MonthlyData LastMonth { get; set; }
        public MonthlyData PreviousMonth { get; set; }
    }
}

Now, let’s create another class and name it MonthlyData. In this class, we define a Data property of type ICollection of MonthlyItem, and a Label property of type string.

using System.Collections.Generic;

namespace FinanceMentor.Client.Services
{
    public class MonthlyData
    {
        public ICollection<MonthlyItem> Data { get; set; }
        public string Label { get; set; }
    }
}

Last but not least, let’s create another class and name it MonthlyItem. This class contains a decimal Amount property and a string Category property.

namespace FinanceMentor.Client.Services
{
    public class MonthlyItem
    {
        public decimal Amount { get; set; }
        public string Category { get; set; }
    }
}

Implement the DataService

Now that we defined all the data classes and the IDataService interface, we need to implement the DataService. Let’s create another class in the Services folder and name it DataService.

We need to call the backend API in this service. Let’s inject an instance of the HttpClient type in the constructor of the DataService class and save it in a private field.

Let’s derive the class from the IDataService interface. We need to implement the four methods we defined in the interface. To save us time, I paste the implementation of the DataService class before we go through the implementation together.

using FinanceMentor.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace FinanceMentor.Client.Services
{
    public class DataService : IDataService
    {
        private readonly HttpClient _httpClient;
        private readonly int _currentYear = DateTime.Today.Year;

        public DataService(HttpClient http)
        {
            _httpClient = http;
        }

        public async Task<ICollection<YearlyItem>> LoadCurrentYearEarnings()
        {
            var data = await _httpClient.GetFromJsonAsync<Earning[]>("api/Earnings");
            return data.Where(earning => earning.Date >= new DateTime(_currentYear, 1, 1)
                && earning.Date <= new DateTime(_currentYear, 12, 31))
                .GroupBy(earning => earning.Date.Month)
                .OrderBy(earning => earning.Key)
                .Select(earning => new YearlyItem
                {
                    Month = GetMonthAsText(earning.Key, _currentYear),
                    Amount = earning.Sum(item => item.Amount)
                })
                .ToList();
        }

        public async Task<ICollection<YearlyItem>> LoadCurrentYearExpenses()
        {
            var data = await _httpClient.GetFromJsonAsync<Expense[]>("api/Expenses");
            return data.Where(expense => expense.Date >= new DateTime(_currentYear, 1, 1)
                && expense.Date <= new DateTime(_currentYear, 12, 31))
                .GroupBy(expense => expense.Date.Month)
                .OrderBy(expense => expense.Key)
                .Select(expense => new YearlyItem
                {
                    Month = GetMonthAsText(expense.Key, _currentYear),
                    Amount = expense.Sum(item => item.Amount)
                })
                .ToList();
        }

        public async Task<ThreeMonthsData> LoadLast3MonthsEarnings()
        {
            var currentMonth = DateTime.Today.Month;
            var lastMonth = DateTime.Today.AddMonths(-1);
            var previousMonth = DateTime.Today.AddMonths(-2);

            return new ThreeMonthsData
            {
                CurrentMonth = new MonthlyData
                {
                    Data = await GetMonthlyEarnings(currentMonth, _currentYear),
                    Label = GetMonthAsText(currentMonth, _currentYear)
                },
                LastMonth = new MonthlyData
                {
                    Data = await GetMonthlyEarnings(lastMonth.Month, lastMonth.Year),
                    Label = GetMonthAsText(lastMonth.Month, lastMonth.Year)
                },
                PreviousMonth = new MonthlyData
                {
                    Data = await GetMonthlyEarnings(previousMonth.Month, previousMonth.Year),
                    Label = GetMonthAsText(previousMonth.Month, previousMonth.Year)
                }
            };
        }

        private async Task<ICollection<MonthlyItem>> GetMonthlyEarnings(int month, int year)
        {
            var data = await _httpClient.GetFromJsonAsync<Earning[]>("api/Earnings");
            return data.Where(earning => earning.Date >= new DateTime(year, month, 1)
                && earning.Date <= new DateTime(year, month, LastDayOfMonth(month, year)))
                .GroupBy(earning => earning.Category)
                .Select(earning => new MonthlyItem
                {
                    Amount = earning.Sum(item => item.Amount),
                    Category = earning.Key.ToString()
                })
                .ToList();
        }

        public async Task<ThreeMonthsData> LoadLast3MonthsExpenses()
        {
            var currentMonth = DateTime.Today.Month;
            var lastMonth = DateTime.Today.AddMonths(-1);
            var previousMonth = DateTime.Today.AddMonths(-2);

            return new ThreeMonthsData
            {
                CurrentMonth = new MonthlyData
                {
                    Data = await GetMonthlyExpenses(currentMonth, _currentYear),
                    Label = GetMonthAsText(currentMonth, _currentYear)
                },
                LastMonth = new MonthlyData
                {
                    Data = await GetMonthlyExpenses(lastMonth.Month, lastMonth.Year),
                    Label = GetMonthAsText(lastMonth.Month, lastMonth.Year)
                },
                PreviousMonth = new MonthlyData
                {
                    Data = await GetMonthlyExpenses(previousMonth.Month, previousMonth.Year),
                    Label = GetMonthAsText(previousMonth.Month, previousMonth.Year)
                }
            };
        }

        private async Task<ICollection<MonthlyItem>> GetMonthlyExpenses(int month, int year)
        {
            var data = await _httpClient.GetFromJsonAsync<Expense[]>("api/Expenses");
            return data.Where(expense => expense.Date >= new DateTime(year, month, 1)
                && expense.Date <= new DateTime(year, month, LastDayOfMonth(month, year)))
                .GroupBy(expense => expense.Category)
                .Select(expense => new MonthlyItem
                {
                    Amount = expense.Sum(item => item.Amount),
                    Category = expense.Key.ToString()
                })
                .ToList();
        }

        private static int LastDayOfMonth(int month, int year)
        {
            return DateTime.DaysInMonth(year, month);
        }

        private static string GetMonthAsText(int month, int year)
        {
            return month switch
            {
                1 => $"January {year}",
                2 => $"February {year}",
                3 => $"March {year}",
                4 => $"April {year}",
                5 => $"May {year}",
                6 => $"June {year}",
                7 => $"July {year}",
                8 => $"August {year}",
                9 => $"September {year}",
                10 => $"October {year}",
                11 => $"November {year}",
                12 => $"December {year}",
                _ => throw new NotImplementedException(),
            };
        }
    }
}

First of all, let’s create a missing variable that holds the current year.

Next, let’s discuss the general idea behind the implementation of all four methods. We call one of the API endpoints we implemented in a previous video of this Crash Course. Next, we use LINQ to transform the data into the structure we need for the Dashboard, and finally, we return the data using the data classes we defined before.

I don’t want to spend more time discussing the data layer of the Dashboard. Let’s move on and implement the Blazor part of the Dashboard next.

The only thing left to do is to register the DataService in the dependency injection container. Let’s open the Program.cs file and register the service.

builder.Services.AddScoped<IDataService, DataService>();

Implementing the Bar Chart

Back on the Index page, we remove the existing template and replace it with the following snippet. In this snippet, I defined a row using Bootstrap CSS classes.

<div class="row">
    <div class="col-lg-8">
        <div class="card">
            <div class="card-header">
                @currentYear - Earnings and Expenses
            </div>
            <div class="card-body">

            </div>
        </div>
    </div>
</div>

Let’s create the code section and define the currentYear field.

@code {
  private static int currentYear = DateTime.Today.Year;
}

Now let’s implement the bar chart together. First of all, we use the RadzenChart component. Next, we use the RadzenColumnSeries component.

This component represents a series of data points that will be rendered in the bar chart. Let’s assign a color to the Fill property and set the Data property to a variable we will be implementing soon. Next, we set the CategoryProperty to Month and the ValueProperty to Amount. We set the Title property to Earnings and the LineType to LineType.Dashed.

Next, let’s copy the line to create another column for the expense data. We change the color in the Fill property, change the Data property to use the yearlyExpenses variable, and set the title to Expenses.

<div class="row">
    <div class="col-lg-8">
        <div class="card">
            <div class="card-header">
                @currentYear - Earnings and Expenses
            </div>
            <div class="card-body">
                <RadzenChart>
                    <RadzenColumnSeries Fill="#AACDBE" Data="@yearlyEarnings" CategoryProperty="Month" ValueProperty="Amount" Title="Earnings" LineType="LineType.Dashed" />
                    <RadzenColumnSeries Fill="#EA907A" Data="@yearlyExpenses" CategoryProperty="Month" ValueProperty="Amount" Title="Expenses" LineType="LineType.Dashed" />
                    <RadzenColumnOptions Radius="5" />
                    <RadzenValueAxis Formatter="@FormatAsUSD">
                        <RadzenGridLines Visible="true" />
                        <RadzenAxisTitle Text="Amount in USD" />
                    </RadzenValueAxis>
                </RadzenChart>
            </div>
        </div>
    </div>
</div>

We use a few more options and components to make the chart look better. I prepared a snippet that I’m going to insert here.

Next, we need to implement the missing variables in the code section of the index page.

Let’s start with the FormatAsUSD method. I insert another snippet.

Next, we define the fields that hold the data for our charts.

private ICollection<YearlyItem> yearlyExpenses;
private ICollection<YearlyItem> yearlyEarnings;

string FormatAsUSD(object value)
{
  return ((double)value).ToString("C0", CultureInfo.CreateSpecificCulture("en-US"));
}

Loading Data for the Bar Charts

Now, let’s add the missing using statements at the top of the component. 

@using System.Globalization;
@using FinanceMentor.Client.Services;
@using FinanceMentor.Client.Components;
@inject IDataService _dataService;

We also inject an instance of type IDataService that we will be using to retrieve the data from the API.

In the code section, we implement the OnInitializedAsync method to load the data when the component is rendered on the screen.

protected override async Task OnInitializedAsync()
{
    yearlyExpenses = await _dataService.LoadCurrentYearExpenses();
    yearlyEarnings = await _dataService.LoadCurrentYearEarnings();

    StateHasChanged();
}

We also call the StateHasChanged method at the end of the method to make sure that the component re-renders when the data is loaded.

That was a lot of code. Let’s start the application to see our changes in action.

Blazor App: Bar Charts using the Radzen component library

Blazor App: Bar Charts using the Radzen component library

As you can see, we now have a bar chart with bars for the expenses and earnings for every month in the current year. Sure, we had to implement a lot of data access code, but the Blazor code we used to create the bar chart is less than 50 lines of code.

Building the Pie Chart Component

Before we celebrate too much, let’s continue with the Dashboard by implementing the Pie chart component. We will use components from the Radzen library again. 

This time, we want to implement a reusable component because we will use the PieChart component multiple times in the Dashboard.

Let’s create a new component in the Components folder and name it PieChart. I’ll insert a snippet for the template definition.

<div>
    <div style="margin-top: 15px; margin-right: 90px; text-align: center;"><b>@Data.Label</b></div>
    <RadzenChart>
        <RadzenPieSeries Fills="@Colors"
                         Data="@Data.Data"
                         Title="@Data.Label"
                         CategoryProperty="Category"
                         ValueProperty="Amount" />
    </RadzenChart>
</div>

We define a div where we show a label for the chart. We also use the RadzenChart component again. This time, we use the RadzenPieSeries component as its child component. Again, we fill a few required properties.

Next, let’s implement the component code. We want to make the variables available from the host of the component. 

First, we define a Colors property of type ICollection of string. This variable holds the colors that will be used in the pie chart.

Next, we define a Data property of type MonthlyData. Let’s add a using statement for the FinanceMentor.Client.Services namespace.

Finally, we define a Label property of type string.

To make all the properties available from the hosting component, we add the Parameter attribute.

@using FinanceMentor.Client.Services;

<div>
    <div style="margin-top: 15px; margin-right: 90px; text-align: center;"><b>@Data.Label</b></div>
    <RadzenChart>
        <RadzenPieSeries Fills="@Colors"
                         Data="@Data.Data"
                         Title="@Data.Label"
                         CategoryProperty="Category"
                         ValueProperty="Amount" />
    </RadzenChart>
</div>

@code {
    [Parameter]
    public ICollection<string> Colors { get; set; }

    [Parameter]
    public MonthlyData Data { get; set; }

    [Parameter]
    public string Label { get; set; }
}

Using the PieChart Component on the Dashboard

Back in the Index.razor file, let’s use the PieChart component. I insert another code snippet. 

@if (earnings != null)
{
    <div class="row mt-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">
                    Earnings - Last 3 Months
                </div>
                <div class="card-body">
                    <div style="display: flex">
                    </div>
                </div>
            </div>
        </div>
    </div>
}

Again, we use Bootstrap to create a row, and we use a Bootstrap Card. In the card body, we add three charts to display the last three months’ earnings data.

Let’s add the code before we work on the template. We create a private field that holds the colors for the pie charts.

private ICollection<string> colors = new List<string>() { "#FBC687", "#F4F7C5", "#93ABD3" };

Next, we add a private earnings variable of type ThreeMonthsData. It will hold the data we want to display in the pie charts. In the OnInitializedAsync method, we call the dataService to load data into the earnings variable using the LoadLast3MonthsEarnings method.

@code {
    private static int currentYear = DateTime.Today.Year;
    private ICollection<string> colors = new List<string>() { "#FBC687", "#F4F7C5", "#93ABD3" };
    private ICollection<YearlyItem> yearlyExpenses;
    private ICollection<YearlyItem> yearlyEarnings;
    private ThreeMonthsData earnings;
    private ThreeMonthsData expenses;

    protected override async Task OnInitializedAsync()
    {
        earnings = await _dataService.LoadLast3MonthsEarnings();
        expenses = await _dataService.LoadLast3MonthsExpenses();
        yearlyExpenses = await _dataService.LoadCurrentYearExpenses();
        yearlyEarnings = await _dataService.LoadCurrentYearEarnings();

        StateHasChanged();
    }

    string FormatAsUSD(object value)
    {
        return ((double)value).ToString("C0", CultureInfo.CreateSpecificCulture("en-US"));
    }
}

Now, let’s add the PieChart component to the template.

@if (earnings != null)
{
    <div class="row mt-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">
                    Earnings - Last 3 Months
                </div>
                <div class="card-body">
                    <div style="display: flex">
                        <PieChart Colors="@colors" Data="@earnings.CurrentMonth" />
                        <PieChart Colors="@colors" Data="@earnings.LastMonth" />
                        <PieChart Colors="@colors" Data="@earnings.PreviousMonth" />
                    </div>
                </div>
            </div>
        </div>
    </div>
}

We use the colors variable for the Colors property, and we use the different properties on the earnings object for the Data property to show all three months in a PieChart each.

Now let’s copy the template and the defined variables to do the same for the expenses.

@if (expenses != null)
{
    <div class="row mt-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">
                    Expenses - Last 3 Months
                </div>
                <div class="card-body">
                    <div style="display: flex">
                        <PieChart Colors="@colors" Data="@expenses.CurrentMonth" />
                        <PieChart Colors="@colors" Data="@expenses.LastMonth" />
                        <PieChart Colors="@colors" Data="@expenses.PreviousMonth" />
                    </div>
                </div>
            </div>
        </div>
    </div>
}

The completed Index.razor page looks like this:

@page "/"
@using FinanceMentor.Client.Services;
@using System.Globalization;
@using FinanceMentor.Client.Components;
@inject IDataService _dataService;

<div class="row">
    <div class="col-lg-8">
        <div class="card">
            <div class="card-header">
                @currentYear - Earnings and Expenses
            </div>
            <div class="card-body">
                <RadzenChart>
                    <RadzenColumnSeries Fill="#AACDBE" Data="@yearlyEarnings" CategoryProperty="Month" ValueProperty="Amount" Title="Earnings" LineType="LineType.Dashed" />
                    <RadzenColumnSeries Fill="#EA907A" Data="@yearlyExpenses" CategoryProperty="Month" ValueProperty="Amount" Title="Expenses" LineType="LineType.Dashed" />
                    <RadzenColumnOptions Radius="5" />
                    <RadzenValueAxis Formatter="@FormatAsUSD">
                        <RadzenGridLines Visible="true" />
                        <RadzenAxisTitle Text="Amount in USD" />
                    </RadzenValueAxis>
                </RadzenChart>
            </div>
        </div>
    </div>
</div>

@if (earnings != null)
{
    <div class="row mt-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">
                    Earnings - Last 3 Months
                </div>
                <div class="card-body">
                    <div style="display: flex">
                        <PieChart Colors="@colors" Data="@earnings.CurrentMonth" />
                        <PieChart Colors="@colors" Data="@earnings.LastMonth" />
                        <PieChart Colors="@colors" Data="@earnings.PreviousMonth" />
                    </div>
                </div>
            </div>
        </div>
    </div>
}

@if (expenses != null)
{
    <div class="row mt-4">
        <div class="col-lg-8">
            <div class="card">
                <div class="card-header">
                    Expenses - Last 3 Months
                </div>
                <div class="card-body">
                    <div style="display: flex">
                        <PieChart Colors="@colors" Data="@expenses.CurrentMonth" />
                        <PieChart Colors="@colors" Data="@expenses.LastMonth" />
                        <PieChart Colors="@colors" Data="@expenses.PreviousMonth" />
                    </div>
                </div>
            </div>
        </div>
    </div>
}

@code {
    private static int currentYear = DateTime.Today.Year;
    private ICollection<string> colors = new List<string>() { "#FBC687", "#F4F7C5", "#93ABD3" };
    private ICollection<YearlyItem> yearlyExpenses;
    private ICollection<YearlyItem> yearlyEarnings;
    private ThreeMonthsData earnings;
    private ThreeMonthsData expenses;

    protected override async Task OnInitializedAsync()
    {
        earnings = await _dataService.LoadLast3MonthsEarnings();
        expenses = await _dataService.LoadLast3MonthsExpenses();
        yearlyExpenses = await _dataService.LoadCurrentYearExpenses();
        yearlyEarnings = await _dataService.LoadCurrentYearEarnings();

        StateHasChanged();
    }

    string FormatAsUSD(object value)
    {
        return ((double)value).ToString("C0", CultureInfo.CreateSpecificCulture("en-US"));
    }
}

Testing the Final Version of the FinanceMentor Application

That’s it. Let’s build and run the application.

And there it is. We see a beautiful Dashboard on the Home page of the FinanceMentor application. On the first row, we have an overview of all the data for the year 2021. Below, we have monthly charts for the earnings. And if we scroll down, we see the monthly charts for the last three months’ expenses.

Blazor App: Completed Dashboard

Blazor App: Completed Dashboard

For April 2021, we only have Housing and Entertainment. Let’s add a new entry to the April 2021 expenses. We navigate to the Expenses page. In the form on the right, we fill in Dinner as the Subject, select the Food category, set the amount to 25, and press the submit button. We can see the new entry in the list on the left. 

Let’s go to the Home page. We scroll down to the bottom and look at the April 2021 expenses. We see a small slice for the Food category.

Congratulations! You implemented the FinanceMentor application as a practical Blazor WebAssembly application.

Summary

This video is the seventh part of the FREE Blazor Crash Course.

  • You learned about the Radzen Component Library for Blazor applications.
  • You learned how to integrate a third-party user interface library into a Blazor application.
  • You learned how to use the Radzen Component Library to build a Dashboard using the Chart components.
  • You completed the FinanceMentor Blazor WebAssembly application.

What’s Next?

This video concludes the seven-part FREE Blazor Crash Course for now. 

We built a Blazor WebAssembly application and learned everything about Blazor component development, form handling, API handling, building a modal dialog component, CSS handling, using images, and building a Dashboard using a third-party user interface library.

Let me know in the comments if you have any questions about Blazor development. Depending on the feedback, I might create additional episodes in the future or upload a Q and A video.

Don’t worry; I’ll be uploading many additional Blazor and .NET development videos on this channel and onto this blog.

 

Claudio Bernasconi

I'm an enthusiastic Software Engineer with a passion for teaching .NET development on YouTube, writing articles about my journey on my blog, and making people smile.