A first look at Blazor and .NET 8

In this post, Blazor and .NET 8 is used to implement a simple website. I took a .NET 7 project, updated it to .NET 8 and tried out some of the new features in .NET 8.

Code: https://github.com/damienbod/Hostedblazor8Aad

Setup

The project was setup using a .NET 7 project which implements an Azure AD authentication using best practice with a backend for frontend architecture and then updated to .NET 8. The security is implemented in the secure backend and the Blazor components are kept simple. The Blazor.BFF.AzureAD.Template template was used for this which takes care of all the project setup. At present no Microsoft template exists for implementing the security in this recommended way. The templates adds the security headers as best it can.

The project was updated to .NET 8 and all the Nuget packages as well.

<TargetFramework>net8.0</TargetFramework>

Microsoft.Identity.Web is used to implement the OpenID Connect confidential client. An Azure App registration was created for this with the Web client and a user secret. You could also use a certificate instead of a secret which improves the token request in the second step of the OIDC code flow authentication.

The application was started and like in .NET 7 we still have the annoying console warnings because the debugging tools try to add inline scripts to our code. The inline scripts are blocked by the CSP and this should be required for all deployments. I like to develop my application as close as possible to my target deployments, so I always develop with the best possible CSP and HTTPS like in the deployed applications. This prevents having to fix CSP issues when we go live or having to fix links to CSS CDNs or whatever.

We also have a warning in the console logs looking for a JS map file from something we do not use. No idea where or what adds to my development.

2023-05-18 The CSP bug has no been fixed in the latest VS preview release

https://developercommunity.visualstudio.com/t/browserlink-CSP-support-NET-7/10061464

Creating Random data from Arrays

In .NET 8 GetItems() was added to System.Random. I decide to create my test data using this. I created an array of objects and returned this as a span.

public static ReadOnlySpan<MyGridData> GetData()
{
	return _mydata.AsSpan();
}

The Random.Shared.GetItems method can be used to return n-items from my span in a random way. I set this to 24 items which can be then displayed in the Grid.

[HttpGet]
public IEnumerable<MyGridData> Get()
{
	return Random.Shared.GetItems(MyData.GetData(), 24);
}

Using QuickGrid in Blazor

The QuickGrid component was also added in .NET 8. This provides simple Grid features.

The Nuget package needs to be added to the client (WASM) project.

Microsoft.AspNetCore.Components.QuickGrid

The QuickGrid can be used in any Razor page in the WASM application. You need to add the using for the Grid and you can create the grid as required. The Grid has good documentation here:

https://aspnet.github.io/quickgridsamples

@page "/directapi"
@using HostedBlazorAad.Shared
@using Microsoft.AspNetCore.Components.QuickGrid
@inject IAntiforgeryHttpClientFactory httpClientFactory
@inject IJSRuntime JSRuntime

<h3>QuickGrid display using data  Direct API</h3>

@if (myGridData == null)
{
    <p><em>Loading...</em></p>
}
else
{
<hr />

<QuickGrid Items="@FilteredItems" Pagination="@pagination">

    <PropertyColumn Property="@(p => p.Id)" Sortable="true" />

    <PropertyColumn Property="@(c => c.Name)" Sortable="true" Class="name">
        <ColumnOptions>
            <div class="search-box">
                <input type="search" autofocus @bind="nameFilter" @bind:event="oninput" placeholder="name..." />
            </div>
        </ColumnOptions>
    </PropertyColumn>

    <PropertyColumn Property="@(p => p.Colour)" Sortable="true" />
</QuickGrid>

<Paginator State="@pagination" />
}

@code {

    private IEnumerable<MyGridData>? myApiData;
    private IQueryable<MyGridData> myGridData = new List<MyGridData>().AsQueryable();
    private PaginationState pagination = new PaginationState { ItemsPerPage = 8 };
    private string nameFilter = string.Empty;

    GridSort<MyGridData> rankSort = GridSort<MyGridData>
        .ByDescending(x => x.Name)
        .ThenDescending(x => x.Colour)
        .ThenDescending(x => x.Id);

    IQueryable<MyGridData>? FilteredItems => myGridData.Where(x => x.Name.Contains(nameFilter, StringComparison.CurrentCultureIgnoreCase));

    protected override async Task OnInitializedAsync()
    {
        var client = await httpClientFactory.CreateClientAsync();

        var myApiData = await client.GetFromJsonAsync<MyGridData[]>("api/DirectApi");

        if (myApiData != null) myGridData = myApiData.AsQueryable();
    }
}

The 24 random items are displayed in the grid using a paging and a sort with eight items per page. The is client side and not server side paging which is important if using large amounts of data.

Notes

Blazor and .NET 8 will change a lot and new templates and project types are being created for Blazor and .NET 8. Blazor United or whatever it will be called after the release will be a new type of Blazor project and the 3 projects structure will probably be reduced down to one. I hope the security will be improved and I don’t understand why Microsoft still do security in the WASM part of the application when it is hosted in an ASP.NET Core backend.

Links

https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8

https://github.com/damienbod/Blazor.BFF.AzureAD.Template

https://dotnet.microsoft.com/en-us/download/visual-studio-sdks

https://aspnet.github.io/quickgridsamples

5 comments

  1. […] A first look at Blazor and .NET 8 [#.NET #.NET Core #ASP.NET Core #.net8 #aspnetcore #Blazor] […]

  2. […] A first look at Blazor and .NET 8 (Damien Bowden) […]

  3. […] A first look at Blazor and .NET 8 – Damien Bowden […]

  4. […] A first look at Blazor and .NET 8 | Software Engineering (damienbod.com) […]

  5. […] A first look at Blazor and .NET 8 […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.