Thursday, April 25, 2024

.NET Aspire with VS Code, SQLite & SQL Server

In this Tutorial, we will explore .NET Aspire. At first, we will use it with SQLite. Thereafter, we will modify the solution so that it uses a SQL Server Docker image instead of SQLite. All this is done in a terminal window with the help of VS Code. The objective is to serve those who do not use the higher end Visual Studio 2022 IDE.

.NET Aspire Setup

In any terminal window folder, run the following command before you install .NET Aspire:

dotnet workload update 

To install the .NET Aspire workload from the .NET CLI, execute this command:

dotnet workload install 

Check your version of .NET Aspire, with this command:

dotnet workload list

Startup Application

We will start with a .NET 8.0 application that involves a Minimal API backend and a Blazor frontend. Grab the code from this GitHub site:

https://github.com/medhatelmasry/SoccerFIFA

To get a good sense of what the application does, follow these steps:

1) Inside the WebApiFIFA folder, run the following command in a terminal window:

dotnet watch


Try out the GET /api/games endpoint, you should see the following output:


2) Next, let us try the frontend. Inside a terminal window in the BlazorFIFA folder, run this command:

dotnet watch


We know that the application works. However, it is a pain to have to start both projects to get the solution to work. This is where .NET Aspire will come to the rescue.

Converting solution to .NET Aspire

Close both terminal windows by hitting CTRL C in each.

TO add the basic .NET Aspire projects to our solution, run the following command inside the root SoccerFIFA folder:

dotnet new aspire

This adds these artifacts:

  • SoccerFIFA.sln file
  • SoccerFIFA.AppHost folder
  • SoccerFIFA.ServiceDefaults folder

We will add our previous API & Blazor projects to the newly created .sln file by executing the following commands inside the root SoccerFIFA folder:

dotnet sln add ./BlazorFIFA/BlazorFIFA.csproj
dotnet sln add ./WebApiFIFA/WebApiFIFA.csproj
dotnet sln add ./LibraryFIFA/LibraryFIFA.csproj

Next, we need to add references in the SoccerFIFA.AppHost project to the BlazorFIFA and WebApiFIFA projects with these commands:

dotnet add ./SoccerFIFA.AppHost/SoccerFIFA.AppHost.csproj reference ./BlazorFIFA/BlazorFIFA.csproj

dotnet add ./SoccerFIFA.AppHost/SoccerFIFA.AppHost.csproj reference ./WebApiFIFA/WebApiFIFA.csproj

Also, both BlazorFIFA and WebApiFIFA projects need to have references into SoccerFIFA.ServiceDefaults with:

dotnet add ./BlazorFIFA/BlazorFIFA.csproj reference ./SoccerFIFA.ServiceDefaults/SoccerFIFA.ServiceDefaults.csproj

dotnet add ./WebApiFIFA/WebApiFIFA.csproj reference ./SoccerFIFA.ServiceDefaults/SoccerFIFA.ServiceDefaults.csproj

Inside the SoccerFIFA root folder, start VS Code with:

code .

Then, in the Program.cs files of both BlazorFIFA and WebApiFIFA, add this code:

// Add service defaults & Aspire components.
builder.AddServiceDefaults();

In the Program.cs file in SoccerFIFA.AppHost, add this code right before “builder.Build().Run();”:

var api = builder.AddProject<Projects.WebApiFIFA>("backend");
builder.AddProject<Projects.BlazorFIFA>("frontend")
    .WithReference(api);

Now, the relative name for the API app is “backend”. Therefore, we can change the base address to http://backend. Change Constants.cs file in BlazorFIFA to:

public const string ApiBaseUrl = "http://backend/";

Test .NET Aspire Solution

To test the solution, in the SoccerFIFA.AppHost folder, start the application with:

dotnet run

Copy the URL that looks like that underlined below and paste it into your browser:


This is what you should see in your browser:


Click on the app represented by the link on the second row. You should experience the Blazor app:


At this stage we get a sense of what .NET Aspire can do for us. It essentially orchestrates the connection between multiple projects and produce a single starting point in the Host project. Let us take this one step further by converting our backend API so it uses a SQL Server container instead of SQLite.

Using SQL Server instead of SQLite

Stop the application by hitting CTRL C.

IMPORTANT: You will need to ensure that Docker Desktop is running on your computer because SQL Server will start in a container.

Add this package to the WebApiFIFA project:

dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer -v 8.0.0-preview.6.24214.1

Also in WebApiSoccer project Program.cs file, comment out (or delete) this code:

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));

Place the below code just before builder.AddServiceDefaults():

builder.AddSqlServerDbContext<ApplicationDbContext>("sqldata");

In the same the Program.cs file, add the following code right before app.Run() to automatically run Entity Framework migrations during startup:

if (app.Environment.IsDevelopment())
{
    using (var scope = app.Services.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        context.Database.EnsureCreated();
    }
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days.
    // You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

Cleanup the backend API solution from all traces of SQLite with:

  1. Delete SQLite files college.db, college.db-shm, and college.db-wal.
  2. In WebApiFIFA.csproj, delete: <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
  3. Delete the Data/Migrations folder.
We will create new migrations that work with SQL Server, instead of SQLite. Therefore, run the following command from within a terminal window inside folder WebApiFIFA.

dotnet ef migrations add M1 -o Data/Migrations

Configure AppHost to use SQL Server

The AppHost project is the orchestrator for your app. It's responsible for connecting and configuring the different projects and services of your app. Add the .NET Aspire Entity Framework Core Sql Server library package to your SoccerFIFA.AppHost project with:

dotnet add package Aspire.Hosting.SqlServer -v 8.0.0-preview.6.24214.1

Update the contents of the Program.cs file in AppHost project with the following code:

var builder = DistributedApplication.CreateBuilder(args);
var sql = builder.AddSqlServer("sql")
                 .AddDatabase("sqldata");
var api = builder.AddProject<Projects.WebApiFIFA>("backend")
    .WithReference(sql);
    
builder.AddProject<Projects.BlazorFIFA>("frontend")
    .WithReference(api);
 
builder.Build().Run();

The preceding code adds a SQL Server Container resource to your app and configures a connection to a database called sqldata. The Entity Framework classes you configured earlier will automatically use this connection when migrating and connecting to the database.

Run SQL Server Solution

Run the application inside the SoccerFIFA.AppHost folder with:

dotnet run

As we did before, copy and paste the URL from the terminal window into your browser:


Your browser will look like this:


Click on the highlighted link above. Our application works just as it did before. The only difference is that this time we are using SQL Server running in a container:


I hope you found this useful and are able to see the possibilities of this new addition to .NET.