You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Web API部署:配置令牌替换后未生效问题求助

问题:Azure Web API部署后配置令牌未生效,复用CI构建工件失败

我搭建了包含CI、Dev、Test、Acc、Prod的5阶段流水线:CI阶段构建并发布应用工件;非CI阶段先通过AzureResourceManagerTemplateDeployment输出存储URI,再通过DownloadPipelineArtifact、replacetokens、AzureWebApp完成部署。

已验证部署文件中的令牌已被替换,但调试接口仍返回原始令牌#{StorageUri}#。猜测编译后的DLL包含初始配置值,导致JSON配置文件未生效。尝试过IConfigurationRoot.Reload()但无效,希望复用CI构建工件,而非为每个环境单独构建。

应用配置加载代码

private static void AddConfig(this WebApplicationBuilder builder, string fileName)
    => builder.Configuration
           .AddJsonFile($"{configDir}/{fileName}.json", optional: false, reloadOnChange: true)
           .AddJsonFile($"{configDir}/{fileName}.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);

调试控制器代码

public class DebugController(IOptions<StorageSettings> settings) : BaseController
{
    private readonly IOptions<StorageSettings> _settings = settings;

    [HttpGet("Get")]
    public async Task<string> Get()
    {
        return _settings.Value.StorageUri;
    }
}

核心流水线YAML

trigger:
  branches:
    include:
    - master
  paths:
    include:
    - ${appname}$/src/**
    exclude:
    - ${appname}$/tests/**
pr:
  branches:
    include:
    - master
pool:
  vmImage: 'windows-latest'
stages:
- stage: CI
  displayName: "Integration"
  jobs:
  - job: BuildTestPublish
    displayName: "Build and test the application, then publish the artifact."
    steps:
    - task: DotNetCoreCLI@2
      displayName: "NuGet Restore"
      inputs:
        command: "restore"
        projects: |
          ${appname}$/*.sln
    - task: DotNetCoreCLI@2
      displayName: "Build and publish the Artifact"
      inputs:
        command: "publish"
        publishWebProjects: false
        projects: |
          ${appname}$/*.sln
        arguments: "-o $(Build.SourcesDirectory)/Output -c Release"
        zipAfterPublish: false
    - task: PublishBuildArtifacts@1
      displayName: "Publish the build artifacts"
      inputs:
        PathtoPublish: "$(Build.SourcesDirectory)/Output"
        ArtifactName: "${appname}$"
- stage: cdDev
  displayName: Deploy to Development
  variables:
  - name: envName
    value: dev
  dependsOn:
  - CI
  jobs:
  - job: infraDeploy
    displayName: "Deploy Infrastructure"
    steps:
    - task: AzureResourceManagerTemplateDeployment@3
      inputs:
        connectedServiceName: ${service_connection}$
        csmFile: infrastructure/main.bicep
        deploymentOutputs: deploymentOutputs
    - task: PowerShell@2
      name: "outputVariables"
      inputs:
        targetType: inline
        script: |
          $armOutputObj = '$(deploymentOutputs)' | ConvertFrom-Json
          $armOutputObj.PSObject.Properties | ForEach-Object {
            $keyname = $_.Name
            $value = $_.Value.value
            Write-Output "##vso[task.setvariable variable=$keyName;issecret=false;isOutput=true]$value"
          }
        pwsh: true
  - job: softwareDeploy
    dependsOn:
    - infraDeploy
    variables:
    - name: storageUri
      value: $[ dependencies.infraDeploy.outputs['outputVariables.storageUri'] ]
    steps:
    - task: DownloadPipelineArtifact@2
      inputs:
        artifactName: "${appname}$"
        path: "$(Pipeline.Workspace)/${artifactname}$"
    - task: replacetokens@6
      inputs:
        sources: |
          $(Pipeline.Workspace)/${artifact_name}$/appsettings*.json
          $(Pipeline.Workspace)/${artifact_name}$/Configurations/*.json
        tokenPrefix: "#{"
        tokenSuffix: "}#"
    - task: AzureWebApp@1
      inputs:
        azureSubscription: ${service_connection}$
        appName: ${appname}$-app-$(envName)
        package: "$(Pipeline.Workspace)/${artifact_name}$"

Test、Acc、Prod阶段为Dev的重复,仅参数不同,部分信息用${value}$替换。


解决方案

1. 检查配置文件的复制属性

确保appsettings*.json和Configurations目录下的JSON文件,在项目属性中设置复制到输出目录为「始终复制」或「如果较新则复制」。若构建时未将这些文件复制到输出目录,CI发布的工件中将缺失配置文件,替换操作无效,应用会加载嵌入到DLL的默认配置。

2. 确认配置加载路径正确性

检查configDir变量的取值,确保它指向Azure Web App运行时的正确目录(默认根目录为D:\home\site\wwwroot)。若configDir为相对路径,需验证其相对于根目录的位置是否正确,避免加载不到替换后的JSON文件。

3. 移除配置文件的程序集嵌入

若项目.csproj中存在将JSON文件标记为<EmbeddedResource>的配置,会导致应用优先加载嵌入到程序集的配置,而非磁盘上的文件。需移除相关嵌入配置,确保应用加载磁盘文件。

4. 替换IOptions为IOptionsMonitor/IOptionsSnapshot

IOptions是单例模式,仅在应用启动时加载一次配置,后续文件变更不会自动更新。若需动态加载配置,改用IOptionsMonitor(实时监控配置变化)或IOptionsSnapshot(请求范围加载):

public class DebugController(IOptionsMonitor<StorageSettings> settings) : BaseController
{
    private readonly IOptionsMonitor<StorageSettings> _settings = settings;

    [HttpGet("Get")]
    public async Task<string> Get()
    {
        return _settings.CurrentValue.StorageUri;
    }
}

5. 验证流水线路径正确性

检查replacetokens任务的sources路径变量(如${artifact_name}$)是否与CI阶段发布的ArtifactName一致,避免路径错误导致未找到目标文件进行令牌替换。


验证步骤

  1. 登录Azure Web App的Kudu控制台(https://<app-name>.scm.azurewebsites.net/DebugConsole),进入site\wwwroot目录,确认目标JSON文件存在且StorageUri已替换为正确值。
  2. 若文件配置正确,重启Web App确保应用加载最新配置。

内容的提问来源于stack exchange,提问作者Falco van der Meulen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:35:14