Aspire brings powerful tools to streamline development and enhance your project’s capabilities. But how can you implement it in your identity solution?
This article covers the steps to integrate .Net Aspire into a solution that includes IdentityServer and AdminUI. We will start by generating the base solution using the All-in-One template to keep things straightforward. If you're unfamiliar with the All-in-One template, this article provides a detailed introduction.
What is .Net Aspire?
.Net Aspire is a platform designed to help developers create cloud solutions. It is also helpful in creating local development environments and adding analytic tools to test and debug different component integrations. In this article, I will run the All-in-one template with these analytic tools from a local environment using .NET Aspire.
Create an All-in-one Solution
Using the All-in-one template and following its article, create your solution:
dotnet new adminui+ids
-n Articles.IdentityServerAndAdminUI.Aspire
-db SqlServer
-c "Server=localhost;User Id=sa;Password=Password123!;Database=IdentityExpressDb;"
dotnet workload list
If Aspire is installed, it will appear in the list of workloads:
To install Aspire, run this:
dotnet workload install aspire
2. A box will be prompted to input a prefix for the two Aspire projects that will be created.
As prompted, Aspire will create two new projects in your solution:
- AppHost that will be the startup project now. Any project you want to execute through Aspire will be called by in this project.
- ServiceDefaults that contains the services that will be added to your project, like telemetry and health checks.
Integrate IdentityServer in Aspire
Wait! It’s not going to be that quick with the IdentityServer sample. For Aspire to do its magic, we must slightly change the IdentityServer project.
Although Aspire can create its own scaffolding and dependencies, it needs the project that will target to use WebApplication.CreateBuilder(args)
and if you check in Program.cs, IdentityServer departs from Host.CreateDefaultBuilder(args)
. Therefore, we need to substitute the whole Program.cs class with this code:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var startup = new Startup(builder.Environment);
startup.ConfigureServices(builder.Services);
var app = builder.Build();
startup.Configure(app);
app.Run();
}
}
Now, we can follow the same steps we did with AdminUI. This time, Aspire will detect that it has already created the projects it needs, so we only need to confirm that we want to use the same ones, and Aspire will add the dependencies.
Note: After adding .NET Aspire Orchestration, check in Program.cs the new lines added have references to their packages:
using Microsoft.Extensions.Hosting;
Integrate the Database in Aspire
If you just want to run IdentityServer and AdminUI locally with Aspire, that’s it. You can execute the AppHost project, and Aspire will run both using your local database. However, you may also want to pipe the database through Aspire (maybe to deploy it altogether later), so here is how you can do it:
Note: You need to have Docker installed on your machine.
1. First of all, we need to add 2 NuGet packages to the AppHost project:
- Aspire.Hosting.SqlServer
- Jerry.WaitForDependencies.Aspire.Hosting
The first one is to create a SqlServer database with Aspire, the second one contains extension methods to await applications in Aspire.
2. In the Program.cs file of the AppHost project, create a SqlServer instance stored in a Docker volume called “MyDataVolume” and add a database named “IdentityExpressDb”:
var sqlServer = builder
.AddSqlServer("TestServer")
.WithHealthCheck()
.WithDataVolume("MyDataVolume");
var identityExpressDb = sqlServer
.AddDatabase("IdentityExpressDb");
3. Make IdentityServer and AdminUI reference this database:
.WithReference(identityExpressDb)
4. Make each project wait for the database creation before they get executed:
.WaitFor(identityExpressDb)
Altogether, it can look like this:
var builder = DistributedApplication.CreateBuilder(args);
var sqlServer = builder
.AddSqlServer("TestServer")
.WithHealthCheck()
.WithDataVolume("MyDataVolume");
var identityExpressDb = sqlServer
.AddDatabase("IdentityExpressDb");
var adminui = builder.AddProject<Projects.Articles_IdentityServerAndAdminUI_Aspire_AdminUI>(
"articles-identityserverandadminui-aspire-adminui"
)
.WithReference(identityExpressDb)
.WaitFor(identityExpressDb);
builder.AddProject<Projects.Articles_IdentityServerAndAdminUI_Aspire_IdentityServer>(
"articles-identityserverandadminui-aspire-identityserver"
)
.WithReference(identityExpressDb)
.WaitFor(adminui)
.WaitFor(identityExpressDb);
builder.Build().Run();
5. Reference the connection string given by Aspire. Aspire creates an environment variable with the name of the database in the project that has referenced it. In this case, it will be ConnectionStrings__IdentityExpressDb
. Therefore, both projects must call this variable to get the new connection string:
- In the IdentityServer project, substitute these lines in the Startup.cs file:
var identityConnectionString = Configuration
.GetValue(
"IdentityConnectionString",
Configuration.GetValue<string>("DbConnectionString")
);
var identityServerConnectionString = Configuration
.GetValue(
"IdentityServerConnectionString",
Configuration.GetValue<string>("DbConnectionString")
);
With this:
var identityConnectionString = Environment
.GetEnvironmentVariable("ConnectionStrings__IdentityExpressDb");
var identityServerConnectionString = Environment
.GetEnvironmentVariable("ConnectionStrings__IdentityExpressDb");
- In the AdminUI project, add these lines after the builder variable in Program.cs:
builder.Configuration["IdentityConnectionString"] = Environment
.GetEnvironmentVariable("ConnectionStrings__IdentityExpressDb");
builder.Configuration["IdentityServerConnectionString"] = Environment
.GetEnvironmentVariable("ConnectionStrings__IdentityExpressDb");
Note: Remember to remove the connection strings from appsettings.json so they don’t overwrite these new ones.
Run Aspire
As mentioned before, the solution must run from the AppHost project. An example of this article can be found on our github.
What Next?
- Moving your AdminUI All-in-one Template into Production
- If you have any questions about getting Aspire up and running, please don't hesitate to email us at [email protected]. We can offer some assistance.