许多容器集成现在公开
一流的帮助程序
来设置端口、用户名和密码,而无需挖掘内部属性。
这三个设置都可以通过参数安全地提供,从而避免机密泄露到源代码中。
var pgPwd = builder.AddParameter("pg-pwd", secret: true);
builder.AddPostgres("pg")
.WithHostPort(6045) // choose the host-side port
.WithPassword(pgPwd) // reference a secret parameter
新的WithHostPort
、WithPassword
和WithUserName
(或者每个服务的等效扩展方法)可用于PostgreSQL、SQL Server、Redis和几个其他容器资源,从而在整个堆栈中实现一致的声明式控制。
🔗 简化的自定义 URL
9.3 使资源链接 更加智能 且 更易于 放置:
选择链接的显示位置 – 每个链接现在包含一个 UrlDisplayLocation
(SummaryAndDetails
或 DetailsOnly
),以便你可以使诊断链接远离主网格,但仍会在详细信息窗格中看到它们。
相对路径会自动解析 - 将此任务交给助手 "/health"
,然后在 Aspire 分配终结点时,将其重写为完整的主机限定 URL。
每个终结点有多个链接 – 重载 WithUrlForEndpoint
可让你将额外的 URL(文档、管理员 UI、探测)附加到同一终结点,而无需重新定义它。
回调中的终结点帮助程序 – context.GetEndpoint("https")
提取完全解析的终结点,以便你可以以编程方式生成自定义链接。
任何资源的自定义 URL 同样适用于自定义资源。
var frontend = builder.AddProject<Projects.Frontend>("frontend")
// Hide the plain-HTTP link from the Resources grid
.WithUrlForEndpoint("http",
url => url.DisplayLocation = UrlDisplayLocation.DetailsOnly)
// Add an extra link under the HTTPS endpoint that points to /health
.WithUrlForEndpoint("https", ep => new()
Url = "/health", // relative path supported
DisplayText = "Health",
DisplayLocation = UrlDisplayLocation.DetailsOnly
通过这些调整,可以通过在正确的位置显示正确的链接来进一步自定义本地开发堆栈。
🙈 隐藏资源而不“伪造”其状态
从历史上来看,唯一能够将资源从仪表板中移除的方法是将其置于Hidden
状态中,这种权宜之计也使资源在 API 中看起来呈现“终结”状态,例如WaitForResourceAsync
。 在 9.3 中,每个快照现在都带有 布尔 IsHidden
标志,完全将 可见性 与 生命周期状态分离。
更简洁的默认设置 - 低级别辅助工具如 AddParameter
和 AddConnectionString
会将自己标记为隐藏,从而不会使用户界面混乱:
var apiKey = builder.AddParameter("api-key", secret: true); // IsHidden = true ✔
准确的等待与健康流 – WaitForResourceAsync
已更新以将 IsHidden
视为单独的谓词,因此隐藏的资源仍然可以被程序等待或显示,而无需进行特殊处理。
此小更改可消除模型中的歧义,同时精确控制仪表板中显示的内容。
🔔 新的生命周期事件
.NET Aspire 9.3 引入了两个新的生命周期事件,以便更轻松地生成具有可预测行为的自定义资源,而无需依赖诸如 Task.Run 或轮询之类的技巧。
InitializeResourceEvent
此事件在 添加资源后触发,但在 分配终结点之前。 它特别适用于没有内置生命周期(如容器或可执行文件)的自定义资源,让你有一个干净的位置来启动后台逻辑、设置默认状态或连接行为。
例如,在初始化时,此最小自定义资源会发布正在运行的状态:
var myCustom = new MyCustomResource("my-resource");
builder.AddResource(myCustom);
builder.Eventing.Subscribe<InitializeResourceEvent>(myCustom, async (e, ct) =>
await e.Notifications.PublishUpdateAsync(e.Resource,
s => s with { State = KnownResourceStates.Running });
这将替换在构造函数或方法内部出现的尴尬模式,例如 Task.Run
或 Configure()
。 可以在官方示例存储库的 Aspire看到更复杂的版本。
ResourceEndpointsAllocatedEvent
分配资源终结点后(例如,在端口解析或容器分配之后),就会触发此事件。 它按资源进行范围限定,因此您可以安全地获取 EndpointReference 并生成衍生的 URL 或诊断信息。
builder.Eventing.Subscribe<ResourceEndpointsAllocatedEvent>((e, ct) =>
if (e.Resource is IResourceWithEndpoints resource)
var http = resource.GetEndpoint("http");
Console.WriteLine($"Endpoint http - Allocated {http.IsAllocated}, Port: {http.Port}");
return Task.CompletedTask;
这些事件使资源创作更加流畅、更安全和更具确定性 -- 无需生命周期猜测。
🌐 YARP 集成(预览版)
.NET Aspire 9.3 引入了 对 YARP (又一个反向代理)的预览支持,这是一个长期请求的补充,用于将反向代理引入 Aspire 应用程序模型。
通过此集成,可以轻松地将轻型代理容器添加到分布式应用,由官方 YARP 容器映像提供支持。 它目前仅支持基于配置的路由,使用您提供的JSON文件。
向应用 Aspire 添加反向代理:
builder.AddYarp("apigateway")
.WithConfigFile("yarp.json")
.WithReference(basketService)
.WithReference(catalogService);
配置文件装载到容器中,用作运行时 YARP 配置。
示例 yarp.json:
"ReverseProxy": {
"Routes": {
"catalog": {
"ClusterId": "catalog",
"Match": {
"Path": "/catalog/{**catch-all}"
"basket": {
"ClusterId": "basket",
"Match": {
"Path": "/basket/{**catch-all}"
"Clusters": {
"catalog": {
"Destinations": {
"catalog/d1": {
"Address": "http://catalog/"
"basket": {
"Destinations": {
"basket/d1": {
"Address": "http://basket/"
调用.WithReference(...)
会自动确保代理容器能够通过catalog
的内部网络图按名称(basket
,Aspire)解析引用的服务。
⚠️ 此预览版中的已知限制
仅支持基于配置的路由。 基于代码或编程的路由生成尚不可用。
配置文件不是作为 发布作的一部分部署的, 你必须手动管理该文件。
由于主机到容器的网络限制,容器到项目的路由将无法正常工作Podman。
💡 想要了解有关创作 YARP 配置的详细信息? 请参阅官方 YARP 文档。
🧪 此集成以预览版提供 - API 和行为可能会演变。 欢迎反馈!
MySQL
AddDatabase
现在创建数据库
在 .NET Aspire 9.3 版本中,MySQL 集成现在支持通过 API 自动创建数据库——这一行为与对 AddDatabase
和 SQL Server 的支持相匹配。
以前,在.AddDatabase("dbname")
的应用程序模型中调用MySQL某个Aspire资源仅创建了逻辑引用,它未在服务器上创建数据库。 这种不匹配引发了混淆,尤其是在用户期望 Aspire 像对其他集成一样预配数据库时。
✅ 9.3 中的新行为:
var mysql = builder.AddMySql("db");
mysql.AddDatabase("appdb");
在运行时,Aspire 现在在运行中的 CREATE DATABASE
容器或服务器上对 "appdb"
执行 MySQL 命令。 如果数据库已存在,则会安全地跳过该命令。
使 MySQL 与更广泛的 Aspire 数据库生态系统保持一致:
自动创建数据库?
有关要求以及如何开始的更多详细信息,请参阅 GitHub 仪表板中的 .NET Aspire Copilot。
🧠 记住筛选器设置
仪表板 .NET.NET Aspire 现在 会记住会话之间的资源筛选器设置 。 以前,如果筛选了“资源”视图(例如,若要隐藏支持服务或仅突出显示前端应用),则这些筛选器在页面重载时重置。
从9.3版本开始,筛选器状态将保留在本地存储中,因此即使在刷新或重启后,您的选择也会保持不变。 通过这种小改进,可以更轻松地专注于最重要的应用部分,尤其是在具有许多支持服务(如 SQL 或队列) Redis的大型图形中。
🧵 未添加监控的资源现在显示在追踪中
在 9.3 中,仪表板现在可以 直观显示对不发出其自己的遥测数据的资源的传出调用,例如数据库、缓存和其他缺少内置跟踪的基础结构组件。
以前,这些依赖项在 跟踪 视图中不可见,除非它们发出 OTLP 跟踪。 现在,如果您的应用程序对一个Redis 未自行发出跨度的建模Aspire进行 HTTP、SQL 或 调用,那么Aspire 仍会在跟踪时间线中将其显示为引用的对等方。
这有助于您。
了解依赖项的完整链 - 即使某些组件是被动的
调试对未监控服务的调用时的延迟或故障
使跟踪 UI 在基础结构类型之间保持一致
💡对于像 SQL Server、PostgreSQL、Redis 或 Blob 存储这样存在传出客户端遥测,但服务本身不参与分布式跟踪的服务尤其有用。
🧪 无需进行检测工具更改,Aspire 根据资源引用推断映射。
这样,无论在何处都能立即访问常见目标(如管理员 UI、运行状况检查和文档)。
这些改进把 Aspire 仪表板转变为一个真正的控制平台,使得导航分布式应用变得更加顺畅和专注,摩擦更少,重点更清晰。
⏸️ 度量指标暂停警告
当指标集合暂停时,仪表板现在会显示 警告横幅 。 这清楚地表明,如果暂时停止遥测数据,数据可能已过时。
📝 控制台日志中的友好名称
当资源只有一个副本时,Aspire仪表板现在使用友好资源名称(例如frontend
,apigateway
或redis
)而不是frontend-0
的副本 ID(如)。
此小更改使日志更易于读取和减少视觉干扰,尤其是在开发过程中常见的单实例设置中。
在多副本方案中, Aspire 仍使用完整副本 ID,以便区分实例。
🚀 部署和发布
🏗️ 对预览版发布者模型和计算环境支持的改进
在 9.2 版本中,我们推出了“发布器”的首次迭代,这是一种灵活的方法,可以在应用托管环境中配置部署到任何云。 为了确保更大的灵活性, .NET.NET Aspire 9.3 包括一个新的 和改进 的发布者模型,用于在应用程序图中分发发布行为,而不是依赖于单个顶级发布者。
与其通过调用Docker或类似方式来选择目标环境(如Azure或AddDockerComposePublisher()
),Aspire现在包含一个内置发布者,用于在每个资源上查找PublishingCallbackAnnotation
。 此注释描述应如何发布该资源,例如,作为 Docker Compose 服务、 Kubernetes 清单或 Azure Bicep 模块。
✅ 这种体系结构转变为 混合部署和异类部署奠定了基础,其中同一应用中的不同服务可以部署到不同的目标(云、边缘、本地)。
大多数应用只需要一个环境
在典型应用中,只需添加 单个计算环境,例如:
builder.AddAzureContainerAppEnvironment("env");
在这种情况下,Aspire 会将正确的发布行为应用于应用模型中的所有计算资源,无需额外的配置。
多个环境需要消除歧义
如果添加 多个计算环境, Aspire 则需要知道哪个资源将转到何处。 计算环境将其转换应用于 所有适用的计算资源 (项目、容器、可执行文件)。 如果多个环境与给定资源匹配, Aspire 则发布时引发 不明确的环境异常 。
可以使用 WithComputeEnvironment(...)
:
var k8s = builder.AddKubernetesEnvironment("k8s-env");
var compose = builder.AddDockerComposeEnvironment("docker-env");
builder.AddProject<Projects.Api>("api")
.WithComputeEnvironment(compose);
builder.AddProject<Projects.Frontend>("frontend")
.WithComputeEnvironment(k8s);
本例展示了如何将服务明确地映射到不同的计算目标,例如,在Kubernetes 中实现前端,在Docker Compose 中实现后端。
💡 想象一个真实场景,您的前端部署到 CDN 或 GitHub Pages,而后端在 Azure Container Apps 上运行。 这种新模型使未来成为可能。
⚠️ 所有以前的发布者注册 API(如 AddDockerComposePublisher()
)都已被删除,以支持此新模型。
支持的计算环境
.NET Aspire 9.3 对以下环境资源提供预览支持:
AddDockerComposeEnvironment(...)
AddKubernetesEnvironment(...)
AddAzureContainerAppEnvironment(...)
AddAzureAppServiceEnvironment(...)
— 请参阅新的应用服务支持→
这些部署目标代表您应用模型中可转换并生成适用于基础设施的特定工件。
Docker 撰写增强功能
.NET Aspire 9.3 引入了强大的新功能,用于使用基于强类型、基于 C# 的配置自定义 Docker Compose 输出。 现在,可以直接从应用模型以声明方式配置全局 Compose 文件和单个Aspire,从而使部署输出易于推理、自定义和自动化。
🛠️ 自定义 Compose 文件和服务定义
现在,可以使用两个新 API 以编程方式配置顶级 Compose 文件和每个服务的行为:
ConfigureComposeFile(...)
— 自定义 docker-compose.yml
元数据
PublishAsDockerComposeService(...)
— 修改任何计算资源的生成服务(如容器或项目)
builder.AddDockerComposeEnvironment("env")
.WithProperties(env =>
env.BuildContainerImages = false; // skip image build step
.ConfigureComposeFile(file =>
file.Name = "aspire-ai-chat"; // sets the file name
// Add a container to the app
builder.AddContainer("service", "nginx")
.WithEnvironment("ORIGINAL_ENV", "value")
.PublishAsDockerComposeService((resource, service) =>
service.Labels["custom-label"] = "test-value";
service.AddEnvironmentalVariable("CUSTOM_ENV", "custom-value");
service.Restart = "always";
这些 API 提供了一种结构化的强类型方式来修改生成的输出,启用更丰富的 CI 自动化、自定义工具和环境特定的调整,而无需手动编辑 YAML。
🔗 将参数和表达式映射到 Docker Compose
.NET Aspire 现在支持通过环境变量占位符 将应用模型(如参数和引用)中的绑定值绑定到 Docker Compose 定义。
这样就可以轻松地将动态配置(例如,从 CI 管道或机密存储)直接流向最终输出。
builder.AddDockerComposeEnvironment("docker-compose");
var containerNameParam = builder.AddParameter("param-1", "default-name", publishValueAsDefault: true);
builder.AddContainer("service", "nginx")
.WithEnvironment("ORIGINAL_ENV", "value")
.PublishAsDockerComposeService((resource, service) =>
service.ContainerName = containerNameParam.AsEnvironmentPlaceholder(resource);
此处 .AsEnvironmentPlaceholder(...)
的关键 API 指示 Aspire 发出 Compose 变量,例如 ${PARAM_1}
并注册映射,以便 .env
相应地更新文件。
🧠 这与 Compose 模型(无需硬编码值)紧密耦合基础结构参数 Docker ,可跨环境解锁可组合性。
这些增强功能使 Docker Compose 成为 完全可编程的发布目标,非常适合本地开发、基于容器的 CI 工作流和需要结构化控制且没有脆弱 YAML 覆盖的团队。
☸️ Kubernetes 清单自定义
.NET Aspire 9.3 添加了对在发布过程中 以编程方式自定义生成的 Kubernetes 清单 的支持。 这样就可以对 YAML 项目 Aspire 发出精细的控制,而无需编写原始清单覆盖或修补程序。
与 Compose 一样 Docker,Aspire 现在支持 全局环境级设置 和 为每个资源的自定义配置。
🛠️ 配置全局和每个资源的设置
可以使用以下 API 在 C# 中配置 Kubernetes 输出:
WithProperties(...)
在计算环境中设置全局行为
PublishAsKubernetesService(...)
用于修改其特定 Kubernetes 资源的计算资源
builder.AddKubernetesEnvironment("env")
.WithProperties(env =>
env.DefaultImagePullPolicy = "Always"; // e.g., Always, IfNotPresent
builder.AddContainer("service", "nginx")
.WithEnvironment("ORIGINAL_ENV", "value")
.PublishAsKubernetesService(resource =>
// Add custom deployment-level settings
resource.Deployment!.Spec.RevisionHistoryLimit = 5;
这让你能够全面访问Kubernetes对象模型,从而实现强大的修改,例如:
重写容器映像拉取策略
自定义副本计数或部署策略
将标签或批注注入服务、部署或配置映射
🧠 Aspire 在后台发出标准 Kubernetes 清单,你仍然可以使用 kubectl
、helm
或 GitOps 工作流来部署它们,但现在可以直接从应用定义中配置它们。
🖥️ Aspire CLI 增强功能
🧪 Aspire CLI 仍处于预览状态 ,处于积极开发状态。 在未来版本中,期待更多功能和优化。
📦 若要安装:
dotnet tool install --global aspire.cli --prerelease
Aspire ️ 9.3 CLI 与 Aspire 9.2 项目不兼容。
必须将项目升级到 Aspire 9.3+ 才能使用最新的 CLI 功能。
🔍 更智能的应用主机发现
CLI 现在从当前目录 向上行走 , 以递归方式搜索 应用主机项目的每个级别。 找到后,它会将结果缓存到 .aspire
文件夹中以加快将来的命令速度。
现在,你可以从aspire run
运行像aspire add
、aspire publish
或这样的命令,CLI 将自动解析应用主机。
cd src/frontend
aspire run
⏳ 健康感知仪表板启动
CLI 现在 等待仪表板响应, 然后再将其 URL 打印到终端。 这可确保链接在打开时立即工作-不再有空白页或重试循环。
这些更新使 Aspire CLI 更加可靠、脚本友好,并与开发人员在日常开发期间跨文件夹和项目移动的方式保持一致。
☁️ Azure 糖果
🌐 Azure 应用服务(预览版支持)
.NET Aspire 9.3 引入了 预览版支持,支持 .NET 将项目部署到 Azure 应用服务,这是开发人员使用 Aspire 现有 Azure 环境时请求最多的功能之一。
通过此集成,可以将项目部署为容器化 Linux Web 应用,该应用使用新 Aspire API 直接在应用主机中AddAzureAppServiceEnvironment(...)
建模。
🚧 当前限制(预览版)
第一个版本的范围限定为最常见的用例:
仅支持 .NET 项目 (通过 AddProject(...)
)
每个项目都必须公开 单个公共 HTTP 终结点
项目作为容器Azure发布到容器注册表
不支持应用主机中的容器
不支持现有应用服务计划
应用服务尚未托管仪表板 Aspire仪表板
📢 托管的仪表板支持即将推出 - 我们正在积极开发此功能。 欢迎提供反馈!
示例:部署到 Azure 应用服务
builder.AddAzureAppServiceEnvironment("env");
builder.AddProject<Projects.Api>("api")
.WithExternalHttpEndpoints()
.PublishAsAzureAppServiceWebsite((infra, site) =>
site.SiteConfig.IsWebSocketsEnabled = true;
在本示例中:
Aspire 预配应用服务计划和 Web 应用
项目被构建为容器并发布到 Azure 容器注册表
容器将按照您提供的配置部署到应用服务 (App Service)
🧠 使用 PublishAsAzureAppServiceWebsite(...)
自定义站点配置、身份验证或 SKU 等设置。
💬 此功能以 预览版提供 - 我们正在寻求你的反馈,因为我们正在扩展支持!
📤 使用现有的 Azure 容器注册表(ACR)
.NET Aspire9.3 添加了对使用新 Azure API 对现有AddAzureContainerRegistry(...)
建模的支持。 这样,便可以 将映像推送到已管理的 ACR,而无需 Aspire 预配新映像。
这非常适合以下团队:
跨环境共享集中式注册表
集成到现有的 CI/CD 管道和发布工作流中
需要对映像发布进行精细控制
示例:将 ACR 与 Azure Container Apps 环境相关联
var acr = builder.AddAzureContainerRegistry("my-acr");
builder.AddAzureContainerAppEnvironment("env")
.WithAzureContainerRegistry(acr);
builder.AddProject<Projects.Api>("api")
.WithExternalHttpEndpoints();
在本示例中:
ACR 在 Aspire 中建模,并由容器应用环境使用。
Aspire 将生成的映像发布到 my-acr
其中并将其配置为 Azure Container Apps 从中拉取
ACR 适用于多个计算环境
可以将以下 AzureContainerRegistryResource
项关联到:
AddAzureContainerAppEnvironment(...)
AddAzureAppServiceEnvironment(...)
这样就可以一致地控制发布映像的位置,即使在不同的计算目标之间也是如此。
💡 使用 .RunAsExisting()
或 .PublishAsExisting()
对 ACR 资源引用现有注册表而不预配一个注册表。
🖇️ Blob 容器的资源深度链接
.NET Aspire 9.3 扩展 资源深层链接 ,包括 Azure Blob Storage 容器 ,基于已在 Cosmos DB、事件中心、服务总线和 AzureOpenAI 中使用的模型。
现在可以直接在应用主机中为单个 Blob 容器建模,然后将作用域范围内的 BlobContainerClient
实例注入服务中,从而轻松读取或写入 blob,而无需手动配置连接字符串或访问。
AppHost:
var builder = DistributedApplication.CreateBuilder(args);
// Add Azure Storage Emulator
var storage = builder.AddAzureStorage("storage").RunAsEmulator();
// Add a blob group and a container
var blobs = storage.AddBlobs("blobs");
var container = blobs.AddBlobContainer("images", blobContainerName: "image-uploads");
// Add the API project and reference the container
builder.AddProject<Projects.my94app_ApiService>("api")
.WithExternalHttpEndpoints()
.WithReference(container);
builder.Build().Run();
在API项目中:
using Azure.Storage.Blobs;
var builder = WebApplication.CreateBuilder(args);
// Register the blob container client
builder.AddAzureBlobContainerClient("images");
var app = builder.Build();
// Minimal POST endpoint for image upload
app.MapPost("/upload", async (
IFormFile file,
BlobContainerClient container) =>
await container.CreateIfNotExistsAsync();
var blob = container.GetBlobClient(file.FileName);
using var stream = file.OpenReadStream();
await blob.UploadAsync(stream, overwrite: true);
return Results.Ok(new { Url = blob.Uri });
app.Run();
此模式为与特定 Blob 容器交互的微服务提供了明确的关注点分离、安全容器范围和最小仪式。
🔐 扩展 Azure Key Vault 的客户端集成
.NET Aspire 9.3 扩展 Azure Key Vault 了对 密钥 和 证书的新客户端集成 API 的支持,使你可以将类型化的 Azure SDK 客户端直接注入服务:
AddAzureKeyVaultKeyClient(...)
AddAzureKeyVaultCertificateClient(...)
AddKeyedAzureKeyVaultKeyClient(...)
AddKeyedAzureKeyVaultCertificateClient(...)
这些 API 补充了现有的 AddAzureKeyVaultClient(...)
,并提供了从 KeyClient
SDK 为 CertificateClient
用户的轻松访问 Azure 和 .NET。
var builder = WebApplication.CreateBuilder(args);
// Register default clients
builder.AddAzureKeyVaultKeyClient("kv");
builder.AddAzureKeyVaultCertificateClient("kv");
// Register named (keyed) clients
builder.AddKeyedAzureKeyVaultCertificateClient("kv", "signing-cert");
通过 键重载,您可以注册多个客户端,这些客户端的作用域均为同一 Key Vault 资源。这在需要根据用途访问多个证书或密钥时非常有用。
🙌 此功能是由 @james古尔德贡献的。 谢谢!
🔑 在环境变量中使用 Key Vault 机密
.NET Aspire9.3 添加了对WithEnvironment(...)
的支持,该重载接受一个IAzureKeyVaultSecretReference
。
这样可以轻松从建模的 Key Vault 中安全地引用机密,而无需硬编码机密值,并确保这些引用正确流入 Bicep 等 Azure 部署输出。
var kv = builder.AddAzureKeyVault("myKeyVault");
var secretRef = kv.Resource.GetSecret("mySecret");
builder.AddContainer("myContainer", "nginx")
.WithEnvironment("MY_SECRET", secretRef);
🧩 从现有的密钥保管库引用保密信息
还可以通过将资源标记为 Azure Key Vault、 或 AsExisting(...)
的方式,将其与 PublishAsExisting(...)
一起使用。 这样,便可以使用 已预配保管库中的机密,非常适合共享环境或团队管理的基础结构。
var keyVaultNameParam = builder.AddParameter("key-vault-name");
var keyVaultResourceGroupParam = builder.AddParameter("key-vault-rg");
var existingVault = builder.AddAzureKeyVault("sharedVault")
.AsExisting(keyVaultNameParam, keyVaultResourceGroupParam);
var apiKey = existingVault.Resource.GetSecret("stripe-api-key");
builder.AddContainer("billing", "mycompany/billing")
.WithEnvironment("STRIPE_API_KEY", apiKey);
此模式可确保 Aspire:
不尝试重新配置 Key Vault
在发布模式下生成正确的现有资源引用
仍可通过环境变量启用机密注入和安全范围
📖 另请参阅: 使用现有 Azure 资源。
🧠 Azure AI 推理客户端集成(预览版)
.NET Aspire9.3 添加了使用Azure库和抽象对Azure.AI.Inference托管聊天完成终结点的仅限客户端支持。
此集成简化了从应用程序调用 AzureOpenAI 或 Azure AI 推理服务(无论是直接使用 SDK 还是使用抽象友好的接口)。
使用 ChatCompletionsClient
与 Azure SDK
builder.AddAzureChatCompletionsClient("connectionName");
app.MapPost("/chat-raw", (
ChatCompletionsClient client,
ChatRequest message) =>
// Use the client
IChatClient
通过Microsoft.Extensions.AI
builder.AddAzureChatCompletionsClient("inference")
.AddChatClient();
注册后,可以使用标准依赖注入来注入 IChatClient。
app.MapPost("/chat", async (
IChatClient chatClient,
ChatRequest message) =>
var result = await chatClient.GetResponseAsync(message.Input);
return result;
此设置与 语义内核等框架无缝集成,适用于模块化或可插入的 AI 系统。
🔗 详细了解 Microsoft.Extensions.AI 和 ChatCompletionsClient。
⚙️ Azure 应用配置客户端的集成
.NET Aspire9.3 通过新的客户端集成添加了对Azure应用配置的支持。📦AspireMicrosoft.Extensions.Configuration.AzureAppConfiguration NuGet 包。
这样,就可以轻松地使用官方 Azure SDK 和 Microsoft.Extensions.Configuration.AzureAppConfiguration
提供程序连接到集中式配置,无需手动设置。
builder.AddAzureAppConfiguration("appconfig");
注册后, Aspire 会自动将 Azure 应用配置连接到应用程序的配置管道。
示例:将Azure 应用配置绑定到应用设置
var builder = WebApplication.CreateBuilder(args);
builder.AddAzureAppConfiguration("appconfig");
var app = builder.Build();
app.MapGet("/feature", (IConfiguration config) =>
var isEnabled = config.GetValue<bool>("FeatureFlag:Enabled");
return Results.Ok(new { Enabled = isEnabled });
app.Run();
动态功能标志评估
跨环境集中配置管理
安全集成到 Aspire 的托管模型中
🔐 与所有 Azure 集成在 Aspire 中一样,应用配置客户端默认使用 托管标识 进行安全访问,无需连接字符串。
📦NuGet 包:Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration
🔗了解有关应用配置的详细信息Azure
🛡️ 通过 Azure 安全的多应用访问 SQL(重大变更)
在 .NET.NET Aspire 9.2 中,在SQL Server使用相同的多个项目Azure Container Apps可能会无提示地破坏应用的标识模型。
每个应用都分配了自己的 托管标识,但 Aspire 已授予 管理员对 部署的最后一个应用的访问权限,覆盖了以前部署的任何应用的访问权限。 这导致了一些混乱的故障,一次只能有一个应用与数据库进行通信。
✅ 9.3 中的新行为
.NET Aspire 9.3 通过以下方式修复此问题:
将一个标识分配为SQL Server管理员
生成一个 SQL 脚本,该脚本:
为每个额外的托管标识创建一个用户
为每个用户在目标数据库上分配 db_owner
角色
这可确保引用数据库的每个应用都获得 完全访问权限 ,而不会与其他应用冲突。
这为什么重要
支持多个应用安全地访问同一个SQL Server
跨应用标识保留最小特权分离
避免早期版本中存在的脆弱“先到者为王”的管理员行为
在云原生环境中启用更丰富的部署方案,例如 Azure Container Apps
⚠️ 破坏性变化
如果您的部署依赖于Aspire将托管标识设置为SQL Server管理员,则需要审查您的访问控制模型。 应用现在接收 显式基于角色的访问(db_owner
) 而不是广泛的管理员权限。
📖 相关: dotnet/aspire#8381 和 dotnet/aspire#8389
💸 默认 Azure SQL SKU 现在使用免费方案(重大变更)
.NET Aspire9.3 将在预配Azure SQL 数据库时使用的默认 SKU 更改为 GP_S_Gen5_2(常规用途无服务器)层, 并采用 免费套餐。 这有助于在开发和试验期间降低意外成本。
以前, Aspire 默认为 “常规用途”(GP) 层 ,没有 免费套餐,即使小应用或测试应用也会产生费用。
预配如下所示的 SQL 数据库时:
var sql = builder.AddAzureSqlServer("sqlserver");
sql.AddDatabase("appdb");
Aspire 现在会自动使用 免费优惠 用于 appdb
,除非你覆盖它,否则将部署 GP_S_Gen5_2 (常规用途无服务器架构)。
如何还原以前的行为
如果你的应用需要常规用途付费层的性能或功能,则可以选择退出新的默认值,使用:
sql.AddDatabase("appdb")
.WithDefaultAzureSku(); // Uses the previous (General Purpose) default
如果要指定要使用的 SKU,请使用 ConfigureInfrastructure
方法,如下所述:设置特定 SKU。
⚠️ 破坏性变化
此更改会影响新部署中的成本、性能和可用功能。 如果应用依赖于更高级别的功能,请确保相应地配置 SKU。
🔧对.WithDefaultAzureSku()
使用还原到旧行为
🚀 AZD:针对 Aspire 应用的 CI/CD 的主要改进
我们极大地改进了 azd
配置基于 Aspire 的应用程序的 CI/CD 管道的方法。 这些更新直接解决了社区报告的最令人沮丧的难题之一:跨环境安全地管理环境参数和机密。
Aspire 应用越来越由参数驱动, 使用基础结构定义的设置,例如连接字符串、运行时版本、API 密钥和功能标志。 将这些值安全且一致地引入 CI 管道(例如 GitHub Actions)在历史上一直很困难。 此版本修复了此问题。
🧠 更智能的参数处理 - 不再使用 AZD_INITIAL_ENVIRONMENT_CONFIG
以前, Aspire 需要基础结构参数的应用依赖于名为 AZD_INITIAL_ENVIRONMENT_CONFIG
的隐藏环境变量。 此变量是包含所有本地环境配置的大型 JSON Blob。 它必须手动传递到 CI 管道,很难检查,并在共享或更新环境时产生摩擦。
现在:azd
Aspire直接从基础结构定义中提取参数,并在管道中以命名环境变量或机密的形式公开这些参数, 安全且显式地公开这些参数。
param openaiKey string
param dbPassword string
AZURE_OPENAI_KEY: ${{ secrets.AZURE_OPENAI_KEY }}
AZURE_DB_PASSWORD: ${{ secrets.AZURE_DB_PASSWORD }}
这意味着不再捆绑、不再脆弱的配置黑客,也不再猜测 CI 中环境的配置方式。
🔤 一致、可预测的参数命名
Aspire 参数使用明确的规则映射到环境变量名称:
将 camelCase
转换为 SNAKE_CASE
将短划线 (-
) 替换为下划线 (_
)
将所有内容大写
将前缀设为 AZURE_
Aspire 自动导出到 CI 的参数
Aspire 应用通常会在 Bicep 或基础结构模块中定义所需的参数,包括 API 密钥、凭据或运行时配置等内容。 这些现在使用上述命名规则自动导出到您的管道配置。
不再需要:
在 .azure/env-name/config.json 中手动配置这些配置
将它们通过复杂的 JSON 数据块注入 CI。
担心本地和云之间缺少或不匹配的配置
安全参数(如 openaiKey
或 dbPassword
)会自动被视为 CI 机密,而其他参数则作为变量注入 -- 全部由其 azd
处理。
🧼 GitHub 中的交互式机密管理
运行 azd pipeline config
时, azd
现在将检测并提示你,如果存储库中 GitHub 已存在机密,或者不再使用机密:
现有机密提示:
The secret AZURE_OPENAI_KEY already exists. What would you like to do?
[1] Keep it
[2] Keep ALL existing secrets
[3] Overwrite it
[4] Overwrite ALL secrets
未使用的机密提示:
The secret AZURE_OLD_SECRET is no longer used. What would you like to do?
[1] Keep it
[2] Keep ALL unused secrets
[3] Delete it
[4] Delete ALL unused secrets
这可确保:
你永远不会对秘密修改感到惊讶
可以保持存储库没有过时的配置
CI 反映实际基础结构设置
🔄 端到端、可 Aspire 重复部署
通过这些更改,应用 Aspire 的从本地到云工作流现在一致且自动化:
将基础结构参数定义为应用的 Aspire 一部分。
azd
在预配过程中捕获它们。
azd pipeline config
将它们映射到 GitHub Actions 或 Azure DevOps 管道。
您的流水线将使用与本地环境相同的所有输入安全运行,且无需手动步骤。
不再有AZD_INITIAL_ENVIRONMENT_CONFIG
。 不再有脆弱的替代。 只需清楚、安全、参数化部署。
这些更改为项目解锁了更流畅、更安全的 CI/CD 体验 Aspire , 减少手动配置,提高安全性,并与生产管道保持本地开发设置一致。
💔 重大变更
每次发布时,我们都努力让.NET.NET Aspire变得更好。 然而,某些变更可能会破坏现有功能。 9.3 中 .NET.NET Aspire 引入了以下重大更改:
.NET Aspire 9.3 中的重大变更