Getting started with .NET Aspire
This article will guide you through building your first .NET Aspire application. If you want an overview of .NET Aspire and what it brings to the table, check out our What is .NET Aspire article.
Prerequisites
There are a few things you need to have ready before you get started with .NET Aspire:
- Visual Studio 2022 Preview (version 17.9 or higher)
- with the .NET Aspire workload installed
- and .NET 8.0
- Docker Desktop
If you prefer not to use Visual Studio, you can also install .NET Aspire using the dotnet CLI using the dotnet workload install aspire
command. And then you are free to use whichever IDE you like.
For a comphrehensive guide on how to install all the required .NET Aspire prerequisites, check out How to install .NET Aspire.
Create new project
In Visual Studio, go to File > New > Project, select .NET Aspire in the project type dropdown, or search for the work “Aspire”. This should bring up two templates:
- .NET Aspire Application – an empty .NET Aspire project template.
- .NET Aspire Starter Application – a more comprehensive project template containing a Blazor frontend, an API backend service, and – optionally – chaching using Redis.
We will choose the .NET Aspire Starter Application template for our first .NET Aspire app.
Give your project a name, and make sure that, in the Additional information dialog, you enable the Use Redis for caching option. This is entirely optional, but it serves as a good example of what .NET Aspire can do for you.
Using dotnet CLI
You can also create .NET Aspire apps using the dotnet CLI. For creating an app using the .NET Aspire Starter Application template, use the following command, replacing Foo
with your desired solution name.
dotnet new aspire-starter --use-redis-cache --output Foo
Code language: PHP (php)
Project structure
With the .NET Aspire solution created, let’s have a look at it’s structure. You should have 4 projects under your solution:
- ApiService: an ASP.NET Core API project used by the frontend to retrieve data.
- AppHost: acts as an orchestrator by connecting and configuring the different projects and services of your .NET Aspire application.
- ServiceDefaults: a shared project used to manage configurations related to resilience, service discovery, and tememetry.
- Web: a Blazor application acting as our frontend.
The dependencies between the projects look like this:
Let’s start at the top.
AppHost project
This is our .NET Aspire solution orchestrator project. It’s role is to connect and configure the different projects and services of our .NET Aspire application.
Let’s have a look at it’s .csproj
file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Foo.ApiService\Foo.ApiService.csproj" />
<ProjectReference Include="..\Foo.Web\Foo.Web.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting" Version="8.0.0-preview.1.23557.2" />
</ItemGroup>
</Project>
Code language: HTML, XML (xml)
Two things will stand out:
- the
IsAspireHost
element which explicitly marks this project as being our solution’s orchestrator - the
Aspire.Hosting
package reference. This package contains core API and abstractions for the .NET Aspire application model. Since the framework is still in preview, the .NET Aspire NuGet packages are marked as preview releases as well.
Let’s look next at Program.cs
. You’ll notice there a very familiar builder pattern used to link together the different projects and to enable caching.
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedisContainer("cache");
var apiservice = builder.AddProject<Projects.Foo_ApiService>("apiservice");
builder.AddProject<Projects.Foo_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
builder.Build().Run();
Code language: C# (cs)
What the code above essentially does is the following:
- creates an
IDistributedApplicationBuilder
instance used to build ourDistributedApplication
- creates a
RedisContainerResource
which we can reference later in our projects and services - adds our
ApiService
project to the application and holds an instance to theProjectResource
- adds our
Web
project to the application, referencing the Redis cache and theApiService
- before finally calling
Build()
to build ourDistributedApplication
instance, andRun()
to run it.
ApiService project
The ApiService
project exposes a /weatherforcast
endpoint which we can consume from our Web
project. In order to make the API available for consumption, we registered it in our AppHost
project, and gave it the name apiservice
.
builder.AddProject<Projects.Foo_ApiService>("apiservice")
Code language: C# (cs)
Web project
The Web
project represents our Blazor frontend and consumes the /weatherforecast
enpoint exposed by our ApiService
. The way it does it is where the .NET Aspire magic starts to really kick in.
You’ll notice that it’s using a typed HttpClient
:
public class WeatherApiClient(HttpClient httpClient)
{
public async Task<WeatherForecast[]> GetWeatherAsync()
{
return await httpClient.GetFromJsonAsync<WeatherForecast[]>("/weatherforecast") ?? [];
}
}
Code language: C# (cs)
Now, if you look inside Program.cs
you will notice something interesting on line 14:
builder.Services.AddHttpClient<WeatherApiClient>(client =>
client.BaseAddress = new("http://apiservice"));
Code language: JavaScript (javascript)
Remember how we gave our ApiService
project the name apiservice
when adding it as a ProjectResource
in our DistributedApplication
? Now this line configures the typed WeatherApiClient
to use service discovery and connect to a service named apiservice
. http://apiservice
will automatically resolve to the correct address of our ApiService
resource without any additional configuration required on your part.
ServiceDefaults project
Similar to the AppHost
project, the shared project is also differentiated through a special project property:
<IsAspireSharedProject>true</IsAspireSharedProject>
Code language: HTML, XML (xml)
The project ensures that all the different projects and services are set up in the same way when it comes to resilience, service discovery, and telemery. It does this by exposing a set of extension methods which can be called by the solution’s projects and services on their own IHostApplicationBuilder
instances.
Run the project
In order to run the project, make sure you have the AppHost
set up as your start project and hit run (F5) in Visual Studio. Alternatively, you can run the project from the command line, using dotnet run --project Foo/Foo.AppHost
, replacing Foo
with your project name.
After the application starts, you will be presented with the .NET Aspire dashboard.
The dashboard allows you to monitor the various parts of your .NET Aspire application: your projects, containers, and executables. It also provides aggregated, structured logs for your services, request traces, and various other useful metrics.
And that’s it! Congratulations on building and running your very first .NET Aspire application!
One Comment