Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Environments provide context for the application to run in. Parameters express the ability to ask for an external value when running the app. Parameters can be used to provide values to the app when running locally, or to prompt for values when deploying. They can be used to model a wide range of scenarios including secrets, connection strings, and other configuration values that might vary between environments.
Parameter values
Parameter values are read from the Parameters
section of the AppHost's configuration and are used to provide values to the app while running locally. When you run or publish the app, if the value isn't configured you're prompted to provide it.
Consider the following example AppHost Program.cs file:
var builder = DistributedApplication.CreateBuilder(args);
// Add a parameter named "example-parameter-name"
var parameter = builder.AddParameter("example-parameter-name");
builder.AddProject<Projects.ApiService>("api")
.WithEnvironment("ENVIRONMENT_VARIABLE_NAME", parameter);
The preceding code adds a parameter named example-parameter-name
to the AppHost. The parameter is then passed to the Projects.ApiService
project as an environment variable named ENVIRONMENT_VARIABLE_NAME
.
Configure parameter values
Adding parameters to the builder is only one aspect of the configuration. You must also provide the value for the parameter. The value can be provided in the AppHost configuration file, set as a user secret, or configured in any other standard configuration. When parameter values aren't found, they're prompted for when you run or publish the app.
Consider the following AppHost configuration file appsettings.json:
{
"Parameters": {
"example-parameter-name": "local-value"
}
}
The preceding JSON configures a parameter in the Parameters
section of the AppHost configuration. In other words, that AppHost is able to find the parameter as it's configured. For example, you could walk up to the IDistributedApplicationBuilder.Configuration and access the value using the Parameters:example-parameter-name
key:
var builder = DistributedApplication.CreateBuilder(args);
var key = $"Parameters:example-parameter-name";
var value = builder.Configuration[key]; // value = "local-value"
Important
However, you don't need to access this configuration value yourself in the AppHost. Instead, the ParameterResource is used to pass the parameter value to dependent resources. Most often as an environment variable.
Prompt for parameter values in the dashboard
If your code adds parameters but doesn't set them, you'll see a prompt to configure their values in the .NET Aspire dashboard. The Unresolved parameters message appears, and you can select Enter values to resolve the problem:
When you select Enter values, .NET Aspire displays a form that you can use to configure values for each of the missing parameters.
You can also control how the dashboard displays these parameters, by using these methods:
WithDescription
: Use this method to provide a text description that helps users understand the purpose of the parameter.WithMarkdownDescription
: Use this method to provide a formatted description in Markdown that explains the parameter's intent.WithCustomInput
: Use this method to provide a callback method that customizes the parameter dialog. For example, in this callback you can customize the default value, input type, label, and placeholder text.
This code shows how to set a description and use the callback:
#pragma warning disable ASPIREINTERACTION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var externalServiceUrl = builder.AddParameter("external-service-url")
.WithDescription("The URL of the external service.")
.WithCustomInput(p => new()
{
InputType = InputType.Text,
#pragma warning restore ASPIREINTERACTION001
Value = "https://example.com",
Label = p.Name,
Placeholder = $"Enter value for {p.Name}",
Description = p.Description
});
var externalService = builder.AddExternalService("external-service", externalServiceUrl);
The code renders this control in the dashboard:
Note
The dashboard parameter dialog includes a Save to user secret checkbox. Select this option to store sensitive values in your AppHost's user secrets for extra protection. For more information about secret parameter values, see Secret values.
Parameter representation in the manifest
.NET Aspire uses a deployment manifest to represent the app's resources and their relationships. Parameters are represented in the manifest as a new primitive called parameter.v0
:
{
"resources": {
"example-parameter-name": {
"type": "parameter.v0",
"value": "{value.inputs.value}",
"inputs": {
"value": {
"type": "string"
}
}
}
}
}
Secret values
Parameters can be used to model secrets. When a parameter is marked as a secret, it serves as a hint to the manifest that the value should be treated as a secret. When you publish the app, the value is prompted for and stored in a secure location. When you run the app locally, the value is read from the Parameters
section of the AppHost configuration.
Consider the following example AppHost Program.cs file:
var builder = DistributedApplication.CreateBuilder(args);
// Add a secret parameter named "secret"
var secret = builder.AddParameter("secret", secret: true);
builder.AddProject<Projects.ApiService>("api")
.WithEnvironment("SECRET", secret);
builder.Build().Run();
Now consider the following AppHost configuration file appsettings.json:
{
"Parameters": {
"secret": "local-secret"
}
}
The manifest representation is as follows:
{
"resources": {
"value": {
"type": "parameter.v0",
"value": "{value.inputs.value}",
"inputs": {
"value": {
"type": "string",
"secret": true
}
}
}
}
}
Connection string values
Parameters can be used to model connection strings. When you publish the app, the value is prompted for and stored in a secure location. When you run the app locally, the value is read from the ConnectionStrings
section of the AppHost configuration.
Note
Connection strings are used to represent a wide range of connection information, including database connections, message brokers, endpoint URIs, and other services. In .NET Aspire nomenclature, the term "connection string" is used to represent any kind of connection information.
Consider the following example AppHost Program.cs file:
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddConnectionString("redis");
builder.AddProject<Projects.WebApplication>("api")
.WithReference(redis)
.WaitFor(redis);
builder.Build().Run();
Note
Using WaitFor with a connection string will implicitly wait for the resource that the connection string connects to.
Now consider the following AppHost configuration file appsettings.json:
{
"ConnectionStrings": {
"redis": "local-connection-string"
}
}
For more information pertaining to connection strings and their representation in the deployment manifest, see Connection string and binding references.
Build connection strings with reference expressions
If you want to construct a connection string from parameters and ensure that it's handled correctly in both development and production, use AddConnectionString with a ReferenceExpression.
For example, if you have a secret parameter that stores a small part of a connection string, use this code to insert it:
var secretKey = builder.AddParameter("secretkey", secret: true);
var connectionString = builder.AddConnectionString(
"composedconnectionstring",
ReferenceExpression.Create($"Endpoint=https://api.contoso.com/v1;Key={secretKey}"));
builder.AddProject<Projects.AspireReferenceExpressions_CatalogAPI>("catalogapi")
.WithReference(connectionString)
.WaitFor(connectionString);
You can also use reference expressions to append text to connection strings created by .NET Aspire resources. For example, when you add a PostgreSQL resource to your .NET Aspire solution, the database server runs in a container and a connection string is formulated for it. In the following code, the extra property Include Error Details
is appended to that connection string before it's passed to consuming projects:
var postgres = builder.AddPostgres("postgres");
var database = postgres.AddDatabase("db");
var pgConnectionString = builder.AddConnectionString(
"pgdatabase",
ReferenceExpression.Create($"{database};Include Error Details=true"));
builder.AddProject<Projects.AspireReferenceExpressions_CustomerAPI>("customerapi")
.WithReference(pgConnectionString)
.WaitFor(pgConnectionString);
Parameter example
To express a parameter, consider the following example code:
var builder = DistributedApplication.CreateBuilder(args);
var db = builder.AddSqlServer("sql")
.PublishAsConnectionString()
.AddDatabase("db");
var insertionRows = builder.AddParameter("insertionRows");
builder.AddProject<Projects.Parameters_ApiService>("api")
.WithEnvironment("InsertionRows", insertionRows)
.WithReference(db);
builder.Build().Run();
The following steps are performed:
- Adds a SQL Server resource named
sql
and publishes it as a connection string. - Adds a database named
db
. - Adds a parameter named
insertionRows
. - Adds a project named
api
and associates it with theProjects.Parameters_ApiService
project resource type-parameter. - Passes the
insertionRows
parameter to theapi
project. - References the
db
database.
The value for the insertionRows
parameter is read from the Parameters
section of the AppHost configuration file appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
},
"Parameters": {
"insertionRows": "1"
}
}
The Parameters_ApiService
project consumes the insertionRows
parameter. Consider the Program.cs example file:
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
int insertionRows = builder.Configuration.GetValue<int>("InsertionRows", 1);
builder.AddServiceDefaults();
builder.AddSqlServerDbContext<MyDbContext>("db");
var app = builder.Build();
app.MapGet("/", async (MyDbContext context) =>
{
// You wouldn't normally do this on every call,
// but doing it here just to make this simple.
context.Database.EnsureCreated();
for (var i = 0; i < insertionRows; i++)
{
var entry = new Entry();
await context.Entries.AddAsync(entry);
}
await context.SaveChangesAsync();
var entries = await context.Entries.ToListAsync();
return new
{
totalEntries = entries.Count,
entries
};
});
app.Run();
See also
.NET Aspire