Azure App Service Hosting integration
The Aspire Azure App Service hosting integration models App Service resources as the AzureAppServiceResource type. To access this type and APIs for expressing them within your AppHost project, install the 📦 Aspire.Hosting.Azure.AppService NuGet package:
dotnet add package Aspire.Hosting.Azure.AppServiceAdd Azure App Service environment
To use Azure App Service with Aspire, you first add an App Service environment to your AppHost project. The environment represents the hosting infrastructure (App Service Plan) where your apps will run.
var builder = DistributedApplication.CreateBuilder(args);
var appServiceEnv = builder.AddAzureAppServiceEnvironment("app-service-env");
// Add other resources to the app model
builder.Build().Run();
The preceding code creates a new Azure App Service environment named app-service-env. When you run your app locally, this environment is provisioned in your Azure subscription with the following resources:
- An App Service Plan with a Premium P0V3 tier on Linux.
- An Azure Container Registry (Basic SKU) for container image storage.
- A user-assigned managed identity for secure access to the container registry.
Important
When you call AddAzureAppServiceEnvironment, it implicitly calls AddAzureProvisioning—which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see Local provisioning: Configuration.
Connect to an existing Azure App Service plan
You might have an existing Azure App Service plan that you want to use. Chain a call to annotate that your AzureAppServiceEnvironmentResource is an existing resource:
var builder = DistributedApplication.CreateBuilder(args);
var existingAppServicePlanName = builder.AddParameter("existingAppServicePlanName");
var existingResourceGroup = builder.AddParameter("existingResourceGroup");
var appServiceEnv = builder.AddAzureAppServiceEnvironment("app-service-env")
.AsExisting(existingAppServicePlanName, existingResourceGroup);
builder.AddProject<Projects.WebApi>("api")
.PublishAsAzureAppServiceWebsite((infra, website) =>
{
// Optional: customize the Azure App Service website here
});
// After adding all resources, run the app...
For more information on treating Azure App Service resources as existing resources, see Use existing Azure resources.
Publish resources as Azure App Service websites
After adding an App Service environment, you can publish compute resources (IComputeResource) as Azure App Service websites using the PublishAsAzureAppServiceWebsite method.
var builder = DistributedApplication.CreateBuilder(args);
var appServiceEnv = builder.AddAzureAppServiceEnvironment("app-service-env");
builder.AddProject<Projects.WebApi>("api")
.PublishAsAzureAppServiceWebsite((infra, website) =>
{
// Optional: customize the Azure App Service website here
});
builder.Build().Run();
The preceding code:
- Creates an Azure App Service environment named
app-service-env. - Adds a project named
apito the AppHost. - Configures the project to be published as an Azure App Service website.
- Provides an optional callback to customize the website configuration.
During local development (when running with ), the project runs locally. When you publish your app, the project is deployed as an Azure App Service website within the provisioned environment.
Note
When you publish resources to Azure App Service using the
PublishAsAzureAppServiceWebsite method, Aspire automatically sets the
AZURE_TOKEN_CREDENTIALS environment variable to managedidentity. This
ensures that DefaultAzureCredential uses only ManagedIdentityCredential
for authentication, following Azure SDK best
practices.
If you need to use a different credential type, you can remove this
environment variable in the PublishAsAzureAppServiceWebsite callback. For
more information, see DefaultAzureCredential behavior in Azure
deployments.
Customize the App Service website
The PublishAsAzureAppServiceWebsite method accepts a callback that allows you to customize the Azure App Service website configuration using the Azure.Provisioning APIs:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddProject<Projects.WebApi>("api")
.PublishAsAzureAppServiceWebsite((infra, website) =>
{
website.AppSettings.Add("ASPNETCORE_ENVIRONMENT", new AppServiceConfigurationSetting
{
Name = "ASPNETCORE_ENVIRONMENT",
Value = "Production"
});
website.Tags.Add("Environment", "Production");
website.Tags.Add("Team", "Engineering");
});
The preceding code:
- Chains a call to
PublishAsAzureAppServiceWebsitewith a customization callback. - Adds an application setting for
ASPNETCORE_ENVIRONMENT. - Adds multiple tags for metadata and organization.
Deployment slots
Deployment slots let you deploy your app to a staging environment for testing before swapping it into production. The WithDeploymentSlot extension method configures a deployment slot for the App Service environment:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureAppServiceEnvironment("appservice")
.WithDeploymentSlot("staging");
var apiService = builder.AddProject<Projects.ApiService>("apiservice")
.WithHttpHealthCheck("/health")
.WithExternalHttpEndpoints();
builder.AddProject<Projects.Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithHttpHealthCheck("/health")
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
The preceding code configures all App Service websites to be deployed to a staging slot.
Deployment slot behavior
When you deploy to a slot, the deployment behavior depends on whether the production App Service already exists:
- New App Service: If the production App Service (production slot) doesn't exist at the time of deployment, Aspire deploys to both the production App Service and the specified deployment slot.
- Existing App Service: If the production App Service already exists, Aspire deploys only to the specified deployment slot.
This behavior allows you to safely deploy and test changes in a staging environment before swapping to production.
Using parameters for deployment slots
You can also specify the deployment slot value as a parameter, allowing the slot name to be provided at deployment time:
var builder = DistributedApplication.CreateBuilder(args);
var slotName = builder.AddParameter("deploymentSlot");
builder.AddAzureAppServiceEnvironment("appservice")
.WithDeploymentSlot(slotName);
// Add your projects and other resources...
builder.Build().Run();
With this configuration, you can specify the slot name when running aspire deploy by providing a value for the deploymentSlot parameter.
Applying customizations to slots
Caution
Customizations applied to the production App Service are not automatically applied to deployment slots. You must explicitly apply any customizations to the slot as well.
When you customize App Service resources using PublishAsAzureAppServiceWebsite or ConfigureInfrastructure, those customizations apply to the production slot by default. If you need the same customizations on your deployment slot, you must apply them separately. This gives you fine-grained control over the configuration of each slot, allowing staging and production environments to have different settings when needed.
Provisioning-generated Bicep
If you're new to Bicep, it's a domain-specific language for defining Azure resources. With Aspire, you don't need to write Bicep by-hand, instead the provisioning APIs generate Bicep for you. When you publish your app, the generated Bicep is output alongside the manifest file.
When you add an Azure App Service environment, the following key resources are provisioned:
- App Service Plan: A Premium P0V3 Linux-based hosting plan.
- Azure Container Registry: A Basic SKU registry for storing container images.
- User-assigned Managed Identity: For secure access between App Service and Container Registry.
- Role Assignments: ACR Pull role assigned to the managed identity.
The generated Bicep is a starting point and is influenced by changes to the provisioning infrastructure in C#. Customizations to the Bicep file directly are overwritten, so make changes through the C# provisioning APIs to ensure they're reflected in the generated files.
Customize provisioning infrastructure
All Aspire Azure resources are subclasses of the AzureProvisioningResource type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources—using the ConfigureInfrastructure API. For example, you can configure the App Service Plan SKU, location, and more. The following example demonstrates how to customize the Azure App Service environment:
var builder = DistributedApplication.CreateBuilder(args);
var appServiceEnv = builder.AddAzureAppServiceEnvironment("app-service-env")
.ConfigureInfrastructure(infra =>
{
var resources = infra.GetProvisionableResources();
var plan = resources.OfType<AppServicePlan>().Single();
plan.Sku = new AppServiceSkuDescription
{
Name = "P1V3",
Tier = "Premium"
};
plan.Tags.Add("Environment", "Production");
plan.Tags.Add("CostCenter", "Engineering");
});
builder.Build().Run();
The preceding code:
- Chains a call to the
ConfigureInfrastructureAPI:- The
infraparameter is an instance of theAzureResourceInfrastructuretype. - The provisionable resources are retrieved by calling the
GetProvisionableResourcesmethod. - The single
AppServicePlanis retrieved. - The
Skuproperty is changed to a P1V3 tier. - Tags are added to the App Service Plan for metadata and organization.
- The
There are many more configuration options available to customize the App Service environment. For more information, see Azure.Provisioning.AppService and Azure.Provisioning customization.