Skip to content
DocsTry Aspire
DocsTry

Set up Azure AI Search in the AppHost

Azure AI Search logo

This article is the reference for the Aspire Azure AI Search Hosting integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.mts — that you use to model an Azure AI Search resource in your AppHost project.

If you’re new to the Azure AI Search integration, start with the Get started with Azure AI Search integrations guide. For how consuming apps read the connection information this page exposes, see Connect to Azure AI Search.

To start building an Aspire app that uses Azure AI Search, install the 📦 Aspire.Hosting.Azure.Search NuGet package:

Terminal
aspire add azure-search

Learn more about aspire add in the command reference.

This updates your aspire.config.json with the Azure AI Search hosting integration package:

aspire.config.json
{
"packages": {
"Aspire.Hosting.Azure.Search": "13.5.3"
}
}

Once you’ve installed the hosting integration in your AppHost project, you can add an Azure AI Search resource as shown in the following examples:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const search = await builder.addAzureSearch("search");
await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj")
.withReference(search);
// After adding all resources, run the app...
await builder.build().run();
  1. When Aspire adds an Azure AI Search resource, it implicitly calls AddAzureProvisioning, which adds support for generating Azure resources dynamically during app startup.

  2. The app must configure the appropriate Azure subscription and location. For more information, see Local provisioning: Configuration.

  3. The withReference call configures a connection in the consuming project named after the referenced search resource, such as search in the preceding example.

Connect to an existing Azure AI Search instance

Section titled “Connect to an existing Azure AI Search instance”

You might have an existing Azure AI Search service that you want to connect to. Chain a call to mark the resource as existing rather than provisioning a new one:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const existingSearchName = await builder.addParameter("existingSearchName");
const search = await builder.addAzureSearch("search");
await search.asExisting(existingSearchName);
await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj")
.withReference(search);
// After adding all resources, run the app...
await builder.build().run();

For more information on treating Azure AI Search resources as existing resources, see Use existing Azure resources.

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 AI Search resource, Bicep is generated to provision the search service with appropriate defaults.

Generated Bicep — search.bicep
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location
resource search 'Microsoft.Search/searchServices@2023-11-01' = {
name: take('search-${uniqueString(resourceGroup().id)}', 60)
location: location
properties: {
hostingMode: 'default'
disableLocalAuth: true
partitionCount: 1
replicaCount: 1
}
sku: {
name: 'basic'
}
tags: {
'aspire-resource-name': 'search'
}
}
output connectionString string = 'Endpoint=https://${search.name}.search.windows.net'
output name string = search.name

The preceding Bicep provisions an Azure AI Search service with disableLocalAuth: true, which means authentication uses role-based access (managed identity) rather than API keys by default. Role assignments are created in a separate module:

Generated Bicep — search-roles.bicep
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location
param search_outputs_name string
param principalType string
param principalId string
resource search 'Microsoft.Search/searchServices@2023-11-01' existing = {
name: search_outputs_name
}
resource search_SearchIndexDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(search.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7'))
properties: {
principalId: principalId
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7')
principalType: principalType
}
scope: search
}
resource search_SearchServiceContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(search.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0'))
properties: {
principalId: principalId
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')
principalType: principalType
}
scope: search
}

The generated Bicep is a starting point and is influenced by changes to the provisioning infrastructure in C#. Customizations to the Bicep file directly will be overwritten, so make changes through the C# provisioning APIs to ensure they are reflected in the generated files.

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:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const search = await builder.addAzureSearch("search");
await search.configureInfrastructure(async (infra) => {
// Customize the provisioning infrastructure here.
// Changes made via the C# AzureResourceInfrastructure API
// are accessible through the infra object.
});
await builder.build().run();

The preceding C# code:

  • Chains a call to the ConfigureInfrastructure API:
    • The infra parameter is an instance of the AzureResourceInfrastructure type.
    • The provisionable resources are retrieved by calling the GetProvisionableResources method.
    • The single SearchService resource is retrieved.
      • The PartitionCount is set to 6.
      • The ReplicaCount is set to 3.
      • The SearchSkuName is set to Standard3.
      • A tag is added to the search resource with a key of ExampleKey and a value of Example value.

For more information, see Azure.Provisioning customization.

By default, the Azure AI Search hosting integration generates role assignments for SearchIndexDataContributor and SearchServiceContributor in the provisioned Bicep. You can customize the roles assigned to a resource:

Use withRoleAssignments to assign specific roles from the AzureSearchRole enum to a resource:

apphost.mts
import { createBuilder, AzureSearchRole } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const search = await builder.addAzureSearch("search");
const api = await builder.addProject("apiservice", "../ExampleProject/ExampleProject.csproj")
.withReference(search);
// Assign only the data-reader role to the api project
await search.withRoleAssignments(api, [AzureSearchRole.SearchIndexDataReader]);
await builder.build().run();

The available roles are defined in the AzureSearchRole enum:

RoleDescription
SearchIndexDataContributorFull access to Azure AI Search index data (read, write, and delete).
SearchIndexDataReaderRead-only access to Azure AI Search index data.
SearchServiceContributorManage search service resources (not data).

For the full reference of Azure AI Search connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see Connect to Azure AI Search.

The Azure AI Search hosting integration doesn’t register a standalone health check by default because Azure AI Search is a managed cloud service. Health verification happens through the C# client integration. For more information, see Connect to Azure AI Search.