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

Azure Web应用程序门户应用设置读取异常问题求助

Azure部署槽应用设置全局生效+启动时读取配置为null问题

问题描述

我有一个托管在Azure上、通过Visual Studio发布的Azure API,希望在Azure门户的应用设置中为不同部署槽的同一键设置不同值,但设置会同步应用到所有部署槽。

该API基于WebApplicationBuilder builder = WebApplication.CreateBuilder(args);创建,我尝试了多种读取配置值的方式:

  • builder.Configuration["VariableName"];
  • Environment.GetEnvironmentVariable("VariableName");
  • builder.Configuration.GetSection("Values").Get<Details>();
    其中Details类定义如下:
    public class Details { public string VariableName { get; set; } }
    

我还添加了builder.Configuration.AddEnvironmentVariables();代码,但无论在Program.cs的哪个位置调用,获取到的值始终为null。

异常现象:API运行后处理请求时能成功读取到值——比如在Program.cs早期调用CosmosDbConfig.initialize(builder.Configuration);并赋值apiKey = configuration["VariableName"];,赋值后立即访问apiKey为null,但API接口被调用时却能返回正确的apiKey值。

应用设置在Azure门户的位置:

对应部署槽的「配置」-「应用程序设置」界面,添加的键值对未勾选「部署槽设置」选项。

完整Program.cs代码

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddEnvironmentVariables();

CosmosDbConfig.initialize(builder.Configuration);

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.Authority = "placeholder";
    options.Audience = "placeholder";
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true
    };
});

builder.Services.AddApplicationInsightsTelemetry(options =>
{
    options.ConnectionString = "placeholder";
});

builder.Services.AddScoped<AuthorizationContext>();
builder.Services.AddScoped<DebugContext>();
builder.Services.AddScoped<JwtValidator>();
builder.Services.AddScoped<RequestorContext>();
builder.Services.AddScoped<GetRequestorObjectsFilter>();

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.AddService<GetRequestorObjectsFilter>();
});

builder.Services.AddSwaggerGen(c =>
{
    string title = builder.Configuration["VariableName"];
    c.SwaggerDoc("v1", new OpenApiInfo { Title = title, Version = "v1" });
});

builder.Services.AddAuthorization();

builder.Services.AddMvc();
builder.Services.AddHttpClient();
builder.Services
    .AddSignalR(hubOptions =>
    {
        hubOptions.AddFilter<ExceptionHandlingHubFilter>();
    })
    .AddAzureSignalR(hubOptions =>
    {
        hubOptions.ConnectionString = "placeholder";
    });
builder.Services.AddCors(options => options.AddPolicy("CorsPolicy", policyBuilder =>
{
    policyBuilder
    .AllowAnyMethod()
    .AllowAnyHeader()
    .AllowCredentials()
    .WithOrigins("placeholder");
}));

builder.Services.AddSingleton(x =>
{
    string accountName = "placeholder";
    string containerName = "placeholder";
    string accountKey = "placeholder";
    string blobServiceEndpoint = $"https://{accountName}.blob.core.windows.net";
    BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri(blobServiceEndpoint), new StorageSharedKeyCredential(accountName, accountKey));
    BlobContainerClient blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName);
    return blobContainerClient;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

LoggerFactoryProvider.LoggerFactory = app.Services.GetRequiredService<ILoggerFactory>();

app.UseMiddleware<ExceptionHandlingMw>();
app.UseMiddleware<AuthorizationMw>();

app.UseSwagger();

app.UseCors("CorsPolicy");
app.UseHttpsRedirection();
app.UseRouting();
app.UseFileServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<MyHub>($"/{SignalRHubData.hubName}");
});

app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");

await ProceduresSetup.run();
app.Run();

解决方案

1. 解决部署槽配置全局同步问题

Azure应用服务中,只有**勾选「部署槽设置」**的配置项才会被标记为「槽专属」,仅对当前部署槽生效;未勾选的配置属于「槽无关」,修改后会同步到所有部署槽。

操作步骤:

  • 进入目标部署槽的「配置」-「应用程序设置」页面
  • 找到目标键值对,点击编辑按钮
  • 勾选「部署槽设置」选项,保存更改即可

2. 解决启动时读取配置为null的问题

ASP.NET Core使用WebApplication.CreateBuilder(args)时,默认已包含环境变量(含Azure应用设置)作为配置源,无需额外调用builder.Configuration.AddEnvironmentVariables();。启动时读取为null的核心原因是Azure槽位配置注入时机滞后:应用启动初期,槽位环境变量尚未完全注入到进程中,而请求处理阶段环境变量已加载完成,因此此时能读取到值。

方法A:延迟读取(推荐)

将启动时需要使用的配置,改为通过依赖注入获取,避免在启动阶段同步读取。以Swagger标题为例:

builder.Services.AddSwaggerGen(c =>
{
    // 使用延迟委托,在Swagger生成时才读取配置
    c.SwaggerDoc("v1", new OpenApiInfo 
    { 
        Title = () => builder.Configuration["VariableName"], 
        Version = "v1" 
    });
});

更规范的方式是使用IOptions模式绑定配置:

  1. 定义配置类:
public class ApiSettings
{
    public string VariableName { get; set; }
}
  1. 在Program.cs中绑定配置:
builder.Services.Configure<ApiSettings>(builder.Configuration);
  1. 在需要使用的服务/控制器中注入IOptions<ApiSettings>:
public class SomeService
{
    private readonly ApiSettings _settings;
    public SomeService(IOptions<ApiSettings> settings)
    {
        _settings = settings.Value;
        // 此处可正常获取_settings.VariableName
    }
}

方法B:强制重新加载配置

在启动时显式触发配置源重新加载,确保Azure环境变量已被加载:

// 在读取配置前调用
await builder.Configuration.ReloadAsync();

builder.Services.AddSwaggerGen(c =>
{
    string title = builder.Configuration["VariableName"];
    c.SwaggerDoc("v1", new OpenApiInfo { Title = title, Version = "v1" });
});

3. 验证配置加载顺序

ASP.NET Core默认配置加载优先级从低到高为:

  1. 内存配置
  2. appsettings.json
  3. appsettings.{Environment}.json
  4. 用户机密(开发环境)
  5. 环境变量
  6. 命令行参数

Azure应用设置以环境变量形式注入,优先级高于本地配置文件。可添加调试代码确认配置源:

foreach (var source in builder.Configuration.Sources)
{
    Console.WriteLine($"配置源类型:{source.GetType().Name}");
}

内容的提问来源于stack exchange,提问作者AaronC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:04:54