Blazor - WebAssembly Full-Stack App with GraphQL

Blazor - WebAssembly Full-Stack App with GraphQL

Getting Started

In this tutorial we will show how you can create a full-stack web application with Blazor WebAssembly and GraphQL with SQL Server as our database.

We will create a MusicApp project, displaying a list of albums and their artists and genres.

Prerequisites

  • Visual Studio 2022
  • SQL Server
  • SQL Server Management Studio (SSMS)

Before getting started you need to have Visual Studio 2022, SQL Server and SQL Server Management Studio installed.

Set up Database

First, we need to create and set up our database.

Open SSMS and create a database named MusicDB.
We will create three tables: Artists, Genres and Albums. Run the following commands:

  CREATE TABLE Artists (
    ArtistId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
    ArtistName nvarchar(255) NOT NULL,
    ActiveFrom date
  );

  CREATE TABLE Genres (
    GenreId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Genre nvarchar(50) NOT NULL
  );

  CREATE TABLE Albums (
    AlbumId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
    AlbumName nvarchar(255) NOT NULL,
    ReleaseDate date NOT NULL,
    ArtistId int NOT NULL,
    GenreId int NOT NULL
    CONSTRAINT FK_Albums_Artists FOREIGN KEY (ArtistId)     
      REFERENCES dbo.Artists (ArtistId)     
      ON DELETE NO ACTION    
      ON UPDATE NO ACTION    
  );
        

After the tables are created successfully we will add some data to them.
Run the following commands:

  INSERT INTO Artists (ArtistName, ActiveFrom)
  VALUES 
    ('Iron Maiden','1975-12-25'),
    ('AC/DC','1973-01-11'), 
    ('Allan Holdsworth','1969-01-01'),
    ('Buddy Rich','1919-01-01'),
    ('Devin Townsend','1993-01-01'),
    ('Jim Reeves','1948-01-01'),
    ('Tom Jones','1963-01-01'),
    ('Maroon 5','1994-01-01'),
    ('The Script','2001-01-01'),
    ('Lit','1988-06-26'),
    ('Black Sabbath','1968-01-01'),
    ('Michael Learns to Rock','1988-03-15'),
    ('Carabao','1981-01-01'),
    ('Karnivool','1997-01-01'),
    ('Birds of Tokyo','2004-01-01'),
    ('Bodyjar','1990-01-01');

  INSERT INTO Genres (Genre)
  VALUES 
    ('Rock'),
    ('Jazz'), 
    ('Country'),
    ('Pop'),
    ('Blues'),
    ('Hip Hop'),
    ('Rap'),
    ('Punk');

  INSERT INTO Albums (AlbumName, ReleaseDate, ArtistId, GenreId)
  VALUES 
    ('Powerslave', '1984-09-03', 1, 1),
    ('Powerage', '1978-05-05', 2, 1), 
    ('Singing Down the Lane', '1956-01-01', 6, 3),
    ('Ziltoid the Omniscient', '2007-05-21', 5, 1),
    ('Casualties of Cool', '2014-05-14', 5, 1),
    ('Epicloud', '2012-09-18', 5, 1),
    ('Somewhere in Time', '1986-09-29', 1, 1),	
    ('Piece of Mind', '1983-05-16', 1, 1),	
    ('Killers', '1981-02-02', 1, 1),	
    ('No Prayer for the Dying', '1990-10-01', 1, 1),	
    ('No Sound Without Silence', '2014-09-12', 9, 4),	
    ('Big Swing Face', '1967-06-01', 4, 2),	
    ('Blue Night', '2000-11-01', 12, 4),	
    ('Eternity', '2008-10-27', 12, 4),	
    ('Scandinavia', '2012-06-11', 12, 4),	
    ('Long Lost Suitcase', '2015-10-09', 7, 4),	
    ('Praise and Blame', '2010-06-26', 7, 4),	
    ('Along Came Jones', '1965-05-21', 7, 4),	
    ('All Night Wrong', '2002-05-05', 3, 2),	
    ('The Sixteen Men of Tain', '2000-03-20', 3, 2);
        

Creating Blazor WebAssembly app

Next, we will create our Blazor WebAssembly application.

Open Visual Studio 2022, click Create a new Project and choose Blazor WebAssembly App.

Create Blazor WebAssembly App

Then at the Configure your new project enter MusicApp as a name of the project.

Configure Blazor WebAssembly App

In the Additional information dialog, select the target framework .NET 6.0 (Long-term support) and set the authentication type to None. Also, check the options Configure for HTTPS and ASP.NET Core hosted and then click Create.

Configure Additional Blazor WebAssembly App

Install Packages

Next, we need to install the NuGet packages that we will be using.
Navigate to Tools - NuGet Package Manager - Package Manager Console. Select MusicApp.Server from Default project dropdown and install the following packages:

  • Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.1 - for the SQL Server database provider
  • Install-Package Microsoft.EntityFrameworkCore.Tools -Version 6.0.1 - for creating models from an existing database
  • Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 6.0.1 - for implementing the JWT authentication mechanism in our app
  • Install-Package HotChocolate.AspNetCore -Version 12.4.1 - GraphQL ASP.NET Core middleware for Hot Chocolate. This package includes the Banana Cake Pop middleware, which provides us with the GraphQL IDE middleware.

    Hot Chocolate is an open-source GraphQL server for the .NET platform that allows us to create GraphQL endpoints. It is easy to set up and allows us to deliver our application quickly by removing the need to build a fully-fledged GraphQL server.

    Banana Cake Pop is a GraphQL IDE that allows us to test the GraphQL server implementations. We can use it with Hot Chocolate or other GraphQL servers.
  • Install-Package HotChocolate.Data.EntityFramework -Version 12.4.1 - for integrating Entity Framework Core into Hot Chocolate.
  • Install-Package HotChocolate.AspNetCore.Authorization -Version 12.4.1 - for enabling the ASP.NET Core authorization integrations for Hot Chocolate.

Scarffolding the Models

Add the connection string in the MusicApp.Server\appsettings.json file as shown below. Replace the value with the connection string for your database.

    "ConnectionStrings": {
      "DefaultConnection": "Data Source=LAPTOP-AAAAAAA;Initial Catalog=MusicDB;Integrated Security=True"
    },
        
After that run the following command in the package manager console to scaffold the models from the database tables:
    Scaffold-DbContext Name=ConnectionStrings:DefaultConnection Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Artists, Genres, Albums
        
Models folder should be created inside MusicApp.Server project. It contains the DB context class, which will have the name of the database followed by the word Context. In our case MusicDBContext.
The MusicDBContext class contains a default empty constructor that we should delete in order not to throw a run time error.

Create a folder named Models inside the MusicApp.Shared project. Move the classes Album.cs, Artist.cs, Genre.cs from the Models folder of the server project to the Models folder of the shared project. This will allow us to share these classes with both the client and the server.

Add Interface

Next, add a folder called Interfaces inside the MusicApp.Server project. Add an interface class IMusic.cs with the following code:

    using MusicApp.Server.Models;

    namespace MusicApp.Server.Interfaces
    {
        public interface IMusic
        {
            Task<List<Genre>> GetGenre();
        }
    }
        

Create Data Access Layer

Create DataAccess folder inside the MusicApp.Server project. Add a class called MusicDataAccessLayer.cs inside this folder with the following code:

    using Microsoft.EntityFrameworkCore;
    using MusicApp.Server.Interfaces;
    using MusicApp.Server.Models;

    namespace MusicApp.Server.DataAccess
    {
        public class MusicDataAccessLayer : IMusic
        {
            readonly MusicDBContext _dbContext;
        
            public MusicDataAccessLayer(IDbContextFactory<MusicDBContext> dbContext)
            {
                _dbContext = dbContext.CreateDbContext();
            }
          
            public async Task<List<Genre>> GetGenre()
            {
                return await _dbContext.Genres.AsNoTracking().ToListAsync();
            }
        }
    }
      

Add GraphQL Query Resolver

Add a folder called GraphQL inside the MusicApp.Server project. Add a class called MusicQueryResolver.cs and put the following code inside it:

    using MusicApp.Server.Interfaces;
    using MusicApp.Server.Models;

    namespace MusicApp.Server.GraphQL
    {
        public class MusicQueryResolver
        {
            readonly IMusic _MusicService;
        
            public MusicQueryResolver(IMusic MusicService)
            {
                _MusicService = MusicService;
            }
          
            [GraphQLDescription("Gets the list of genres.")]
            public async Task<List<Genre>> GetGenreList()
            {
                return await _MusicService.GetGenre();
            }
        }
    }
    
We have injected the IMusic service dependency in this class. The GetGenreList method will invoke the GetGenre method of the music service to fetch the list of genres. The GraphQLDescription attribute is used to describe the function. This description will be available to the client consuming this function.

Configure the Program.cs File

Lastly, we should configure the middleware for our application. Add the following code inside Program.cs file:

    builder.Services.AddPooledDbContextFactory<MusicDBContext>
      (options =>
      options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
  
    builder.Services.AddScoped<IMusic, MusicDataAccessLayer>();
  
    builder.Services.AddGraphQLServer()
      .AddQueryType<MusicQueryResolver>();
  
We are registering our DBContext using the AddPooledDbContextFactory. We have also registered the MusicQueryResolver class with the GraphQL server using the AddQueryType extension method.

Then, add the following code at the end of the file to add the GraphQL endpoint to the endpoint configurations. Add this line before calling the Run() function.
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGraphQL();
    });
  

Result

Now launch the application and append /graphql to the base URL. It will open the Banana Cake Pop IDE in your browser. You can fetch the list of genres like this:

Fetch Genres