Watch Aspire live streamsDocumentaçãoExperimente

Customize Azure resources

Este conteúdo não está disponível em sua língua ainda.

Azure logo

When working with Azure integrations in Aspire, you often need to customize the provisioned infrastructure beyond the default settings. The same customization patterns apply across Azure hosting integrations such as Storage, Service Bus, Key Vault, user-assigned identities, Azure Container Apps, and Azure App Service. This page documents all customization APIs supported across both C# and TypeScript AppHost projects.

For target-specific generated resource customization, see Deploy to Azure Container Apps and Deploy to Azure App Service.

Use AsExisting, RunAsExisting, and PublishAsExisting when you want Aspire to reference an Azure resource that already exists instead of provisioning a new one.

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const existingBusName: ParameterResource
existingBusName
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addParameter(name: string, options?: {
value?: string;
publishValueAsDefault?: boolean;
secret?: boolean;
}): ParameterResource (+1 overload)

Adds a parameter resource

addParameter
("existingServiceBusName");
const
const existingBusResourceGroup: ParameterResource
existingBusResourceGroup
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addParameter(name: string, options?: {
value?: string;
publishValueAsDefault?: boolean;
secret?: boolean;
}): ParameterResource (+1 overload)

Adds a parameter resource

addParameter
("existingServiceBusResourceGroup");
const
const serviceBus: AzureServiceBusResource
serviceBus
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureServiceBus(name: string): AzureServiceBusResource

Adds an Azure Service Bus Namespace resource to the application model. This resource can be used to create queue, topic, and subscription resources.

addAzureServiceBus
("messaging");
await
const serviceBus: AzureServiceBusResource
serviceBus
.
AzureBicepResource.publishAsExisting(name: string | ParameterResource, resourceGroup?: string | ParameterResource): AzureServiceBusResource (+1 overload)

Marks the resource as an existing resource when the application is deployed.

publishAsExisting
(
const existingBusName: ParameterResource
existingBusName
,
const existingBusResourceGroup: ParameterResource
existingBusResourceGroup
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

Use RunAsExisting when only local run mode should use the existing resource, PublishAsExisting when only deployed Azure environments should use it, and AsExisting when both modes should point at the same Azure resource.

Aspire automatically assigns Azure RBAC roles based on how resources reference one another. When you need to opt out of those defaults before applying different permissions, use ClearDefaultRoleAssignments.

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const serviceBus: AzureServiceBusResource
serviceBus
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureServiceBus(name: string): AzureServiceBusResource

Adds an Azure Service Bus Namespace resource to the application model. This resource can be used to create queue, topic, and subscription resources.

addAzureServiceBus
("messaging");
await
const serviceBus: AzureServiceBusResource
serviceBus
.
AzureBicepResource.clearDefaultRoleAssignments(): IAzureResource

Clears all default role assignments for the specified Azure resource.

clearDefaultRoleAssignments
();
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

For built-in and custom RBAC guidance, see Manage Azure role assignments.

Azure resources expose output references for values that Azure assigns during provisioning. Use those references when another resource, deployment step, or app setting needs the resolved Azure value.

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const identity: AzureUserAssignedIdentityResource
identity
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureUserAssignedIdentity(name: string): AzureUserAssignedIdentityResource

Adds an Azure user‑assigned identity resource to the application model.

addAzureUserAssignedIdentity
("identity");
const
const clientId: BicepOutputReference
clientId
= await
const identity: AzureUserAssignedIdentityResource
identity
.
AzureUserAssignedIdentityResource.getOutput(name: string): BicepOutputReference

Gets a reference to an output from a bicep template.

getOutput
("clientId");
const
const api: ProjectResource
api
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addProject(name: string, projectPath: string, options?: {
launchProfileOrOptions?: ProjectResourceOptions;
}): ProjectResource (+1 overload)

Adds a .NET project resource

addProject
("api", "../Api/Api.csproj");
await
const api: ProjectResource
api
.
ProjectResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ProjectResource

Sets an environment variable

withEnvironment
("IDENTITY_CLIENT_ID",
const clientId: BicepOutputReference
clientId
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

Use GetBicepIdentifier() inside ConfigureInfrastructure or infrastructure resolvers when you need a stable identifier for a provisioned Azure construct. Use output references such as ClientId, NameOutputReference, or getOutput("...") when you need Azure-assigned values like a client ID, endpoint, or resource name.

The ConfigureInfrastructure API lets you customize the Azure resources that Aspire generates during provisioning. In C#, it provides a strongly-typed surface over the Azure.Provisioning library, letting you modify any property of the generated Azure resource types before Bicep is emitted.

All Azure hosting resources in Aspire inherit from AzureProvisioningResource, which exposes ConfigureInfrastructure. The callback receives an AzureResourceInfrastructure instance that gives you access to all provisioned constructs for that resource.

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const storage: AzureStorageResource
storage
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureStorage(name: string): AzureStorageResource

Adds an Azure Storage resource to the application model. This resource can be used to create Azure blob, table, and queue resources.

addAzureStorage
("storage");
await
const storage: AzureStorageResource
storage
.
AzureProvisioningResource.configureInfrastructure(configure: (obj: AzureResourceInfrastructure) => Promise<void>): AzureProvisioningResource

Configures the Azure provisioning infrastructure callback

configureInfrastructure
(async (
infra: AzureResourceInfrastructure
infra
) => {
// Strongly-typed Azure SDK types are not available in TypeScript.
// Use getProvisionableResources() to access constructs dynamically.
const
const resources: any[]
resources
= await
infra: AzureResourceInfrastructure
infra
.
AzureResourceInfrastructure.getProvisionableResources(): Promise<any[]>

Gets the provisionable Azure resources produced by the infrastructure callback.

getProvisionableResources
();
// Work with resources generically as needed.
});
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

When an integration creates multiple resources (for example, a Service Bus namespace and its queues), you can customize each one inside a single ConfigureInfrastructure call:

For common scenarios, prefer Aspire’s higher-level resource builders. For example, to add a private endpoint to a storage account, use AddPrivateEndpoint from the Aspire.Hosting.Azure.Network package, which automatically wires up the Private DNS Zone, VNet link, and DNS Zone Group:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const vnet: AzureVirtualNetworkResource
vnet
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureVirtualNetwork(name: string, options?: {
addressPrefix?: string | ParameterResource;
}): AzureVirtualNetworkResource (+1 overload)

Adds an Azure Virtual Network resource to the application model.

addAzureVirtualNetwork
("vnet");
const
const peSubnet: AzureSubnetResource
peSubnet
=
const vnet: AzureVirtualNetworkResource
vnet
.
AzureVirtualNetworkResource.addSubnet(name: string, addressPrefix: string | ParameterResource, options?: {
subnetName?: string;
} | undefined): AzureSubnetResource (+1 overload)

Adds an Azure subnet resource to an Azure Virtual Network resource.

addSubnet
("pe-subnet", "10.0.1.0/24");
const
const storage: AzureStorageResource
storage
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addAzureStorage(name: string): AzureStorageResource

Adds an Azure Storage resource to the application model. This resource can be used to create Azure blob, table, and queue resources.

addAzureStorage
("storage");
const
const blobs: AzureBlobStorageResource
blobs
=
const storage: AzureStorageResource
storage
.
AzureStorageResource.addBlobs(name: string): AzureBlobStorageResource

Adds an Azure Blob Storage resource

addBlobs
("blobs");
const peSubnet: AzureSubnetResource
peSubnet
.
AzureSubnetResource.addPrivateEndpoint(target: IAzurePrivateEndpointTarget): AzurePrivateEndpointResource

Adds an Azure Private Endpoint resource to the subnet.

addPrivateEndpoint
(
const blobs: AzureBlobStorageResource
blobs
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

When no Aspire-native resource builder exists for what you need, fall back to ConfigureInfrastructure to add an Azure.Provisioning construct directly. See the Azure.Provisioning API reference for the available construct types and their properties.

Customize naming and provisioning with an infrastructure resolver

Section titled “Customize naming and provisioning with an infrastructure resolver”

Another way to customize Azure provisioning is to create an InfrastructureResolver. This is a C#-only API that lets you apply organization-wide naming conventions or other centralized provisioning behavior across many Azure resources.

For scenarios requiring full control, you can supply a custom Bicep file and reference it from your AppHost. This approach works in both C# and TypeScript.

Create a Bicep file in your AppHost project:

custom-storage.bicep
@description('Storage account name')
param storageAccountName string
@description('Location')
param location string = resourceGroup().location
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'BlockBlobStorage'
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
}
}
}
output storageAccountName string = storageAccount.name

Reference the file from the AppHost using AddBicepTemplate (C#) or addBicepTemplate (TypeScript). Use WithParameter / withParameter to supply input parameters, and GetOutput / getOutput to consume a named output by passing the resulting reference to another resource:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const storage: AzureBicepResource
storage
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addBicepTemplate(name: string, bicepFile: string): AzureBicepResource

Adds an Azure Bicep resource to the application model.

addBicepTemplate
("storage", "./custom-storage.bicep");
await
const storage: AzureBicepResource
storage
.
AzureBicepResource.withParameter(name: string, options?: {
value?: string | string[] | ParameterResource | IResourceWithConnectionString | BicepOutputReference | ReferenceExpression | EndpointReference;
} | undefined): AzureBicepResource (+1 overload)

Adds a Bicep parameter

withParameter
("storageAccountName", {
value?: string | string[] | ParameterResource | IResourceWithConnectionString | BicepOutputReference | ReferenceExpression | EndpointReference | undefined
value
: "mystorageaccount" });
const
const storageAccountName: BicepOutputReference
storageAccountName
= await
const storage: AzureBicepResource
storage
.
AzureBicepResource.getOutput(name: string): BicepOutputReference

Gets a reference to an output from a bicep template.

getOutput
("storageAccountName");
const
const webapp: ProjectResource
webapp
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addProject(name: string, projectPath: string, options?: {
launchProfileOrOptions?: ProjectResourceOptions;
}): ProjectResource (+1 overload)

Adds a .NET project resource

addProject
("webapp", "../WebApp/WebApp.csproj");
await
const webapp: ProjectResource
webapp
.
ProjectResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ProjectResource

Sets an environment variable

withEnvironment
("STORAGE_ACCOUNT_NAME",
const storageAccountName: BicepOutputReference
storageAccountName
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

WithParameter accepts several kinds of values beyond plain strings, so a custom Bicep template can take values that are computed at deployment time. Common sources include:

  • A ParameterResource declared with AddParameter (including secret parameters).
  • A BicepOutputReference from another Bicep resource — useful when one template’s output feeds another template’s input.
  • A ReferenceExpression that composes values from multiple resources.
  • A connection-string-bearing resource via IResourceBuilder<IResourceWithConnectionString>.
  • An EndpointReference from a resource’s endpoint.

The example below adds a secret administrator password as a parameter and then reads the deployed SQL server name back out of the template so that another resource can consume it:

Create the following Bicep file in your AppHost directory:

custom-sql.bicep
@secure()
param administratorLoginPassword string
param location string = resourceGroup().location
resource sqlServer 'Microsoft.Sql/servers@2021-11-01' = {
name: 'sql-${uniqueString(resourceGroup().id)}'
location: location
properties: {
administratorLogin: 'sqladmin'
administratorLoginPassword: administratorLoginPassword
}
}
output sqlServerName string = sqlServer.name
apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const adminPassword: ParameterResource
adminPassword
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addParameter(name: string, options?: {
value?: string;
publishValueAsDefault?: boolean;
secret?: boolean;
}): ParameterResource (+1 overload)

Adds a parameter resource

addParameter
("adminPassword", {
secret?: boolean | undefined
secret
: true });
const
const sql: AzureBicepResource
sql
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addBicepTemplate(name: string, bicepFile: string): AzureBicepResource

Adds an Azure Bicep resource to the application model.

addBicepTemplate
("sql", "./custom-sql.bicep");
await
const sql: AzureBicepResource
sql
.
AzureBicepResource.withParameter(name: string, options?: {
value?: string | string[] | ParameterResource | IResourceWithConnectionString | BicepOutputReference | ReferenceExpression | EndpointReference;
} | undefined): AzureBicepResource (+1 overload)

Adds a Bicep parameter

withParameter
("administratorLoginPassword", {
value?: string | ParameterResource | string[] | IResourceWithConnectionString | BicepOutputReference | ReferenceExpression | EndpointReference | undefined
value
:
const adminPassword: ParameterResource
adminPassword
});
const
const sqlServerName: BicepOutputReference
sqlServerName
= await
const sql: AzureBicepResource
sql
.
AzureBicepResource.getOutput(name: string): BicepOutputReference

Gets a reference to an output from a bicep template.

getOutput
("sqlServerName");
const
const api: ProjectResource
api
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addProject(name: string, projectPath: string, options?: {
launchProfileOrOptions?: ProjectResourceOptions;
}): ProjectResource (+1 overload)

Adds a .NET project resource

addProject
("api", "../Api/Api.csproj");
await
const api: ProjectResource
api
.
ProjectResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ProjectResource

Sets an environment variable

withEnvironment
("SQL_SERVER_NAME",
const sqlServerName: BicepOutputReference
sqlServerName
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

For more end-to-end examples — including chaining outputs between Bicep resources and using the existing Bicep keyword to reference resources that Aspire didn’t provision — see the Aspire playground/bicep sample.

By default, Aspire deploys Bicep resources at the resource group scope. Some Bicep templates require a different deployment scope, such as the subscription or the tenant.

To see the Bicep that Aspire emits after applying your ConfigureInfrastructure callbacks, publish the AppHost and read the files from the output folder:

  1. From the AppHost directory, run aspire publish.
  2. Open the aspire-output folder in the AppHost directory. To write somewhere else, pass --output-path to the publish command.
  3. Review the generated .bicep files to verify your customizations.