產業新聞

Build 2025:Iron Software客戶的AI與.NET展望

分享一些來自Iron Software工程團隊關於Aspire 13.2版本的筆記。 我們推出.NET程式庫(IronPDFIronOCRIronXLIronWordIronBarcode等),幾乎每個客戶來電都涉及分散式應用程式協調問題。 這就是為什麼我們會關注Aspire的版本更新。 13.2是第一個CLI感覺可以實際替代儀表板以進行大多數日常工作的版本,並且有一些可能會在升級時引起問題的重大變更。

這不是一篇版本說明的重述。 官方的新增功能頁面有詳盡的清單。這是一些在運行中的程式碼庫中實際有用的東西,加上一些需要注意的搭配。

簡而言之

  • CLI現在真正可編寫腳本:分離模式,aspire stop,隔離模式,JSON輸出
  • 如果您想放棄.csproj協作層,TypeScript AppHost現在正在預覽中
  • 配置文件合併到aspire.config.json (舊文件自動遷移)
  • Foundry替代Azure AI Foundry。 這個會破壞您的構建
  • WithBuildSecret
  • 服務發現環境變數現在使用方案而非端點名稱 (靜默破風險)
  • 預設Azure憑證行為在客戶端整合中發生變化

CLI終於成為CLI

這是重點。在13.2之前,aspire run阻塞了您的終端,而儀表板是管理運行中的apphost的唯一現實面。單獨開發可以,但在CI、整合測試或任何代理驅動的工作流程中就顯得不便。

13.2修正了這一點:

# Run in the background
aspire run --detach

# Or the new shortcut
aspire start

# See what's running
aspire ps

# Stop it
aspire stop
aspire stop --all
# Run in the background
aspire run --detach

# Or the new shortcut
aspire start

# See what's running
aspire ps

# Stop it
aspire stop
aspire stop --all
SHELL

結合--format json (發送到stdout,而狀態消息進stderr,很重要如果您在其他地方管道化) ,您可以圍繞這個構建實際的自動化。 aspire ps --resources --format json是編輯器整合和腳本的可靠構建基塊。

隔離模式是不被知曉的英雄

--isolated是我們一直在等待的。 它運行一個apphost,使用隨機化的端口和隔離的使用者秘密,防止端口衝突和配置衝突:

aspire run --isolated
aspire start --isolated
aspire run --isolated
aspire start --isolated
SHELL

如果您曾嘗試同時運行同一apphost的兩個檢出 - 比如主對功能分支,或者平行整合測試,或者代理驅動的工作流程 - 那您應該感受到痛苦。 隨機端口加上分隔密碼意味著最終您可以旋轉N個副本而不必關心。

僅對於git工作樹來說,它就值得升級。 對於帶有原生依賴項(如PDF生成的Chrome渲染,OCR的Tesseract,通常的重量級選手)的實際服務帶來的整合測試套件來說,這是區分不穩定和可靠的關鍵。

aspire doctor and aspire describe

aspire doctor運行您的環境:開發證書狀態、容器運行時版本、.NET SDK、WSL2配置、代理配置。 這種事每個框架都應該具備但大多數不去理會的東西。 輸出是可採取行動的。 當某些事情出錯時,它會告訴您該怎麼做。

aspire describe --follow可以從終端獲得資源狀態的流式視圖。 和儀表板顯示的資料相同,但可以管道化。 將其放入tmux窗格中,您可以在80欄獲得大部分儀表板的價值。

資源命令更整潔

舊的resource-start / resource-stop / resource-restart命令已被淘汰,取而代之的是更乾淨的子命令形式:

aspire resource api restart
aspire resource api rebuild
aspire resource api restart
aspire resource api rebuild
SHELL

rebuild是新的。 它停止、構建並重新啟動單個.NET項目資源而不會拆毀整個apphost會話。 如果您曾經更改過一個服務中的12資源圖,並抱怨需要重啟所有東西,那麼這就是解決方法。 我們自己也有同感:當您在PDF渲染模板上迭代或調整OCR預處理時,只需重新載入一個項目的整個圖形重啟便很快就會過時。

在不離開CLI的情況下處理秘密和證書

兩個新的專用命令組:

aspire certs clean
aspire certs trust

aspire secret set ApiKey super-secret-value
aspire secret list --format json
aspire certs clean
aspire certs trust

aspire secret set ApiKey super-secret-value
aspire secret list --format json
SHELL

aspire secret是更大的獲勝者。 它映射到同一個支持AddParameter(..., secret: true)於應用程式模型中的使用者秘密儲存,但您不需要安裝.NET CLI來管理它們。 在一個多語言apphost中,不是每個開發者都有.NET SDK,這很重要。

aspire等待CI

aspire wait api --status healthy --timeout 120
aspire wait api --status healthy --timeout 120
SHELL

阻止在資源狀態上。 結合sleep 30 && hope

配置:一個文件來統治它們全部

Aspire正在合併其配置文件。 舊的apphost.run.json之間的劃分被消除了,取而代之的是一個在項目根目錄的aspire.config.json

{
  "appHost": {
    "path": "apphost.ts",
    "language": "typescript/nodejs"
  },
  "sdk": { "version": "13.2.0" },
  "channel": "stable",
  "profiles": {
    "default": {
      "applicationUrl": "https://localhost:17000;http://localhost:15000"
    }
  }
}

遷移是自動的。 首次在現有項目中運行任何aspire命令時,舊文件會合併到新格式中,並將路徑重新定位到項目根目錄。 舊文件會被保留,以便您可以同時使用舊版CLI。全域設置 (globalsettings.json) 也會遷移。

如果您有直接接觸apphost.run.json的自動化,請計劃移動它。

TypeScript AppHost(預覽)

即使您當天不使用這個,也很有趣。 您現在可以用TypeScript而不是C#編寫您的apphost:

import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

const cache = await builder.addRedis("cache");

const api = await builder.addProject("api", "../api")
    .withReference(cache)
    .waitFor(cache);

await builder.build().run();

在內部,TS apphost以訪客進程的形式運行,通過本地傳輸與Aspire的.NET協作主機使用JSON-RPC進行通信。 相同的資源模型、相同的儀表板、相同的整合,只是在TypeScript中表達。

有趣的部分是程式碼生成。 當您運行aspire add時,CLI會檢查整合的.NET程式集並生成一個TypeScript SDK進入.modules/aspire run上自動運行)。 13.2生成器還新增了Go、Java和Rust測試目標,這暗示了未來的方向。

對於像我們這樣的.NET優先團隊來說,這更像是"觀看這個"而非"發佈這個",但程式碼生成模式意味著未來的多語言apphost語言都將遵循相同的模型。 查看多語言架構文件以了解主機橋如何工作。

儀表板:遙測資料導出/導入是新玩具

儀表板有了一個真正的導出/導入工作流程。 從設置→管理中,選擇資源和遙測型別並將它們導出為JSON格式,存放於壓縮包中。之後可以再導入到儀表板,或交給其他人(或LLM)進行分析。

aspire export CLI命令產生相同的包:

aspire export --output .\artifacts\aspire-export.zip
aspire export <resource>
aspire export --output .\artifacts\aspire-export.zip
aspire export <resource>
SHELL

對於錯誤報告來說確實有用。 與"這裡有一些截圖和日誌文件"相比,您可以附上一個實際遙測狀態的快照。

其他儀表板側的註釋:

  • 您現在可以直接從儀表板UI設置資源參數,並選擇將其保存到使用者秘密中
  • 環境變數可以導出為.env文件,從資源詳細視圖中
  • 資源圖形佈局使用自適應力驅動定位 複雜的圖形明顯不那麼雜亂
  • /api/telemetry上的遙測HTTP API返回OTLP JSON; 支持?follow=true以進行NDJSON流化。 端點涵蓋資源、跨度、日誌和追踪(包括/traces/{traceId}進行完整追踪查詢)

獨立的儀表板預設將遙測API設為關閉。 如果您自己托管儀表板並依賴於API,您需要DASHBOARD__API__PRIMARYAPIKEY)。 AppHost整合的場景仍然有效,因為Aspire.Hosting為工具自動連接API。

應用程式模型值得注意的點

WithMcpServer

您可以在應用程式模型中聲明一個資源宿主MCP端點:

var api = builder.AddProject<Projects.MyApi>("api")
    .WithMcpServer("/mcp");
var api = builder.AddProject<Projects.MyApi>("api")
    .WithMcpServer("/mcp");
Dim api = builder.AddProject(Of Projects.MyApi)("api") _
    .WithMcpServer("/mcp")
$vbLabelText   $csharpLabel

Aspire工具將能發現並代理這個端點。 如果您正在推出任何向編碼代理公開工具的東西,這是將其接入的最乾淨的方法。 通過選項支持自定義路徑或端點名稱。

上下文端點解析

這是您在需要時才會注意到的東西。 端點現在可以從特定呼叫者或網路的角度來解析:

var endpoint = redis.GetEndpoint("tcp");

var url = await endpoint.GetValueAsync(new ValueProviderContext {
    Caller = containerApp.Resource,
});
var endpoint = redis.GetEndpoint("tcp");

var url = await endpoint.GetValueAsync(new ValueProviderContext {
    Caller = containerApp.Resource,
});
Dim endpoint = redis.GetEndpoint("tcp")

Dim url = Await endpoint.GetValueAsync(New ValueProviderContext With {
    .Caller = containerApp.Resource
})
$vbLabelText   $csharpLabel

相同的Redis端點將根據上下文從主機進程中解析為cache:6379PublicInternet,如果您寧願選擇一個網路而非呼叫者。

版本說明明確指出這些API在13.1中存在但未正確行為。 因此,如果您在13.1中對它們進行了任何操作,請重新測試。詳細資訊請參閱資源層次結構文件

容器構建秘密

WithBuildSecret。 新名稱更清晰。 這些通過Docker/Podman作為正確的構建秘密傳遞,而不是作為構建參數(這些泄漏到映像歷史中)。

builder.AddContainer("worker", "contoso/worker")
    .WithDockerfile("../worker")
    .WithBuildSecret("ACCESS_TOKEN", accessToken);
builder.AddContainer("worker", "contoso/worker")
    .WithDockerfile("../worker")
    .WithBuildSecret("ACCESS_TOKEN", accessToken);
$vbLabelText   $csharpLabel

構建秘密現在也可以是文件 (例如,.npmrc 用於容器構建中的私有註冊機構身份驗證),這涵蓋了大多數真實世界的用例。

整合:重要的那些

完整列表很長。 這些是我會標註的:

  • Docker Compose發布現在穩定(以前是預發布)。 docker-compose.yaml從您的應用程式模型中生成。當"部署到Azure"不是答案時,它是個有用的逃生出口。 值得注意的是,如果您正在推出包含原生依賴項的容器,因為IronPDF、IronOCR和IronXL都支持乾淨的Linux容器和Docker,所以生成的Compose文件通常可以正常工作且不需要手動修改。
  • Azure虛擬網路整合 (Aspire.Hosting.Azure.Network) 讓您可以在apphost中聲明VNets、子網、NSGs、NAT網關和私有端點。AddPrivateEndpoint會自動建立私有DNS區、虛擬網路連結並在目標上禁用公共存取。 這是先前意味著需要維護一個單獨的Bicep文件的事情。
  • Azure Data Lake Storage既獲得了主機支持又獲得了客戶端支持:AddAzureDataLakeServiceClient / AddAzureDataLakeFileSystemClient。DI註冊、重試、健康檢查、遙測,通常的Aspire堆棧。
  • MongoDB EF Core有新的客戶端整合 (Aspire.MongoDB.EntityFrameworkCore)。 EnrichMongoDbContext<TContext>()如果您自己註冊DbContext。
  • Azure AI推理現在支持嵌入式,不僅僅是聊天。 註冊IEmbeddingGenerator<string, Embedding<float>>。 也有鍵控變體可用。
  • Azure Container RegistryWithPurgeTask("0 1 * * *", ago: TimeSpan.FromDays(7), keep: 5),其中提供ACR清除任務在定時任務上。
  • Bun支持JavaScript資源通過WithBun()。 通過AddViteApp的Yarn可靠性。
  • Microsoft Foundry替代Azure AI Foundry。 Aspire.Hosting.Azure.AIFoundry。 重大變更; 詳細資訊在下面。

整理一下:Aspire 13.2中的文件服務

這是我們內部測試配合我們的程式庫的分佈式方案的模式。 值得一提的是,因為大多數新的13.2功能在這種型別的多服務設置中才會獲得回報,而不是在演示中。

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

// A worker service that uses IronPDF for HTML to PDF rendering
var renderer = builder.AddProject<Projects.PdfRenderer>("renderer")
    .WithReference(cache)
    .WaitFor(cache)
    .WithMcpServer("/mcp");

// An OCR worker that uses IronOCR for image and PDF text extraction
var ocr = builder.AddProject<Projects.OcrWorker>("ocr-worker")
    .WithReference(cache);

// API gateway that fans out to both
builder.AddProject<Projects.Api>("api")
    .WithReference(renderer)
    .WithReference(ocr)
    .WaitFor(renderer)
    .WaitFor(ocr);

builder.Build().Run();
var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

// A worker service that uses IronPDF for HTML to PDF rendering
var renderer = builder.AddProject<Projects.PdfRenderer>("renderer")
    .WithReference(cache)
    .WaitFor(cache)
    .WithMcpServer("/mcp");

// An OCR worker that uses IronOCR for image and PDF text extraction
var ocr = builder.AddProject<Projects.OcrWorker>("ocr-worker")
    .WithReference(cache);

// API gateway that fans out to both
builder.AddProject<Projects.Api>("api")
    .WithReference(renderer)
    .WithReference(ocr)
    .WaitFor(renderer)
    .WaitFor(ocr);

builder.Build().Run();
Imports DistributedApplication

Dim builder = DistributedApplication.CreateBuilder(args)

Dim cache = builder.AddRedis("cache")

' A worker service that uses IronPDF for HTML to PDF rendering
Dim renderer = builder.AddProject(Of Projects.PdfRenderer)("renderer") _
    .WithReference(cache) _
    .WaitFor(cache) _
    .WithMcpServer("/mcp")

' An OCR worker that uses IronOCR for image and PDF text extraction
Dim ocr = builder.AddProject(Of Projects.OcrWorker)("ocr-worker") _
    .WithReference(cache)

' API gateway that fans out to both
builder.AddProject(Of Projects.Api)("api") _
    .WithReference(renderer) _
    .WithReference(ocr) _
    .WaitFor(renderer) _
    .WaitFor(ocr)

builder.Build().Run()
$vbLabelText   $csharpLabel

13.2特別帶來的好處:

  • aspire start --isolated讓您能夠並排運行兩個這個圖形的副本而不會端口碰撞。 在比較分支或針對渲染器運行平行整合測試時有用
  • aspire resource renderer rebuild只重新載入PDF渲染器,當您改變了一個Razor模板時,而不是重新振盪整個圖形
  • aspire wait renderer --status healthy --timeout 120讓您的CI在Chrome渲染初始化之前阻止運行PDF生成測試
  • 遙測HTTP API和aspire export為每個渲染呼叫提供OTLP格式的跨度,這是您實際在生產流量中捕捉慢速CSS規則的方法
  • WithMcpServer讓您將渲染器作為MCP工具公開給編碼代理工作流,這在您構建任何程式生成文件時很有用

如果您想建立一個像上面那樣的渲染器服務,IronPDF的HTML到PDF教程會演示C#這一邊。對於OCR工作者,IronOCR入門指南涵蓋了基礎。

將會真正咬住您的重大變更

大致按您可能遇到的順序排列:

服務發現環境變數命名

# Before (13.0/13.1)
services__myservice__myendpoint__0 = https://localhost:5001

# After (13.2)
services__myservice__https__0 = https://localhost:5001
# Before (13.0/13.1)
services__myservice__myendpoint__0 = https://localhost:5001

# After (13.2)
services__myservice__https__0 = https://localhost:5001
SHELL

使用端點方案而不是端點名稱。 如果您有任何程式碼或配置匹配那些環境變數名,請更新它。 這是最有可能的靜默破壞:沒有任何異常,變數只是有不同的鍵。

BeforeResourceStartedEvent

以前更廣泛地觸發; 現在只在實際啟動資源時觸發,而不是在每次狀態變化時。 如果您的處理程式依賴於以前的行為,它將悄悄停止運行。

AIFoundry到Foundry

包和API的重命名。 更新包引用和調用:

<PackageReference Include="Aspire.Hosting.Foundry" Version="13.2.0" />
<PackageReference Include="Aspire.Hosting.Foundry" Version="13.2.0" />
XML
// Before
var ai = builder.AddAzureAIFoundry("ai");

// After
var foundry = builder.AddFoundry("ai");
var project = foundry.AddProject("agents");
var chat = project.AddModelDeployment("chat", FoundryModel.OpenAI.Gpt5Mini);
// Before
var ai = builder.AddAzureAIFoundry("ai");

// After
var foundry = builder.AddFoundry("ai");
var project = foundry.AddProject("agents");
var chat = project.AddModelDeployment("chat", FoundryModel.OpenAI.Gpt5Mini);
' Before
Dim ai = builder.AddAzureAIFoundry("ai")

' After
Dim foundry = builder.AddFoundry("ai")
Dim project = foundry.AddProject("agents")
Dim chat = project.AddModelDeployment("chat", FoundryModel.OpenAI.Gpt5Mini)
$vbLabelText   $csharpLabel

RunAsFoundryLocal仍適用於本地模型開發,但當父資源配置為Foundry Local時,不支持Foundry Projects。

預設Azure憑證

Aspire Azure客戶端整合不再使用無參數DefaultAzureCredential構造函式。 如果您依賴於除ManagedIdentityCredential以外的憑證在Azure服務中工作,行為改變了。 在升級生產環境之前,請閱讀預設Azure憑證文件。

資源命令重命名

resource-start / resource-stop / resource-restart現在是 aspire resource <name> start|stop|restart。 更新任何腳本。--project更為優先(仍被接受)。

連接屬性後綴

新增了一個連接屬性後綴。 如果您直接存取連接屬性(而不是通過WithReference),請檢查您的程式碼仍能解決它們。

WithSecretBuildArg to WithBuildSecret

上面提到了。 只是直接重命名。

IAzureContainerRegistry過時

改用計算環境上的ContainerRegistry屬性。

儀表板遙測API現在需要選擇加入(獨立)

已如上所述,但值得重申:獨立的儀表板部署現在需要明確啟用API。

您應該升級嗎?

對於一個運行多服務應用程式的工作.NET商店,假設您已盤點上述重大變更,是的。 CLI的改進本身就讓它值得。 特別是分離模式和隔離模式修正實際的工作流程問題。

對於Foundry使用者:如果您想從這個版本中獲得任何新內容,重命名就是一個強制遷移,所以要計劃好。

對於對TypeScript感興趣的人:13.2是第一個版本,其中TS apphost足夠真實以供評估。 仍然是預覽,但值得週五下午一試。

如果您已經在13.x上,升級本身是一行命令:

aspire update --self
aspire update
aspire update --self
aspire update
SHELL

如果您在12.x或更早版本,請先點擊升級指南。您不能跳過13.0步驟。

補丁說明:13.2.1

從原始版本發佈以來,13.2.1已發佈,並進行了可靠性修復。 有一個小的TypeScript SDK重命名值得注意,僅在您已經在TS apphost預覽上時才重要:

以前新的
runAsExistingFromParameters(name, resourceGroup)runAsExisting(name, { resourceGroup })
publishAsExistingFromParameters(name, resourceGroup)publishAsExisting(name, { resourceGroup })
withConnectionPropertyValue(name, value)withConnectionProperty(name, value)
withParameterBuildArg(name, parameter)withBuildArg(name, parameter)

withConnectionPropertyValue在生成的SDK中保留作為相容性別名,所以不會導致運行時中斷。

構建具有文件工作負載的分佈式.NET應用程式?

如果您的服務處理PDF生成、OCR、Excel處理、條形碼或我們涵蓋的其他格式,我們的程式庫正是為這種多服務、容器友好的設置而設計的,正如Aspire所協同的。 一切都支持.NET 10、9、8、7、6、Framework和Core,並在Linux容器、Azure、AWS和內部運行。

幾個起始點:

  • IronPDF用於HTML到PDF、PDF編輯、簽名和表單。 教程中心是快速建立工作渲染服務的最快途徑
  • IronOCR適用於圖像和PDF文字抽取,支持超過125種語言
  • IronXL用於不需Office Interop而進行Excel讀寫
  • IronWord用於DOCX生成和編輯
  • IronBarcodeIronQR用於條碼和QR生成和掃描
  • Iron Suite如果您需要以上多個

您可以獲取30天試用金鑰並在不到一小時內將PDF或OCR服務運行在Aspire apphost中。 如果您遇到任何奇怪的問題,我們的支持團隊是實際的工程師,而不是票務分揀隊列。

就是這樣。 下次發佈見。