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

.NET 6 进程内Function App部署Azure后无法读取应用设置值

问题背景

我使用Visual Studio 2022创建了全新的.NET 6进程内(in-process)Function App,项目包含3个计时器(timer)函数。我定义了自定义配置类用于绑定配置项,在本地Visual Studio开发环境运行时功能完全正常。

问题出现在应用部署到Azure之后:由于自定义配置类无法从Function App的应用程序设置中正确加载值,Startup类中的依赖注入(Dependency Injection)流程失败。

相关代码

自定义配置类

public class Settings
{
    public ConnectionStrings ConnectionStrings { get; set; }
    public TwilioSettings TwilioSettings { get; set; }
}

public class TwilioSettings
{
    public string AccountSid { get; set; }
    public string AuthToken { get; set; }
    public string From { get; set; }
}

public class ConnectionStrings
{
    public string ZZZZZZZ { get; set; }
} 

本地local.settings.json配置

{
  "IsEncrypted": false,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  },
  "AzureWebJobsStorage": "UseDevelopmentStorage=true",
  "FUNCTIONS_WORKER_RUNTIME": "dotnet",
  "ConnectionStrings": {
    "ZZZZZZZ": "xxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "TwilioSettings": {
    "AccountSid": "xxxxxxxxxxxxxxxx",
    "AuthToken": "xxxxxxxxxxxxxxxxx",
    "From": "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}

现有Startup.cs配置绑定代码

public override void Configure(IFunctionsHostBuilder builder)
{
    var settings = new Settings();
    var basePath = $"{Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName}\\";
    var jsonPath = $"{basePath.Substring(0, basePath.LastIndexOf('\\'))}\\local.settings.json";
    
    var config = new ConfigurationBuilder()
                .SetBasePath(basePath)
                .AddJsonFile(jsonPath, true)
                .AddEnvironmentVariables()
                .Build();
    config.Bind(settings);

    builder.Services.AddSingleton(settings);
    builder.Services.AddSingleton(settings.TwilioSettings);
    var cs = settings.ConnectionStrings.ZZZZZ;
    builder.Services.AddDbContextFactory<JTMContext>(opt => opt.UseSqlServer(cs));
    builder.Services.AddDbContext<JTMContext>(opt => opt.UseSqlServer(cs));
}

Azure端配置

部署前已提前创建Azure Function App资源,在配置页的应用程序设置(Application Settings)和连接字符串(Connection Strings)中添加了所需键值对:
Azure Function App Configuration

错误现象

从Visual Studio发布Function App后,应用初始状态正常,但任意计时器函数触发时会抛出如下错误:

Microsoft.Extensions.DependencyInjection.Abstractions: Value cannot be null. (Parameter 'implementationInstance').

错误出现在Startup.cs的Configure()方法注册自定义Settings单例的环节,排查发现手动实例化的IConfigurationRoot对象config没有加载Azure端的应用程序设置。


解决方案

你现在手动new ConfigurationBuilder从零构建配置的写法,从根上就不符合Azure Functions进程内模型的配置加载规则,两个核心问题直接导致Azure上配置读不到:

  1. 本地能跑纯粹是因为你本地有local.settings.json文件,部署到Azure后生产环境根本不会带这个文件。而且你加的AddEnvironmentVariables()也读不到Azure Function的应用设置——Functions的应用设置加载逻辑宿主已经做了特殊处理,不是简单读普通环境变量就能拿到的。
  2. 你自己写的路径拼接逻辑在Azure托管环境完全不生效,Azure Functions运行时的目录结构和本地调试的目录结构不一样,就算文件存在你也找不到路径。

正确做法是直接用Functions宿主已经构建完成的IConfiguration实例,完全没必要自己从头搭配置管道:

public override void Configure(IFunctionsHostBuilder builder)
{
    // 直接拿宿主构建好的配置,已经自动加载了本地local.settings.json、Azure应用设置、连接字符串等所有配置源
    var config = builder.GetContext().Configuration;
    
    var settings = new Settings();
    config.Bind(settings);

    // 提前做空校验,比等DI注入时报null错误好排查
    if (settings.ConnectionStrings == null || string.IsNullOrWhiteSpace(settings.ConnectionStrings.ZZZZZZZ))
    {
        throw new InvalidOperationException("数据库连接字符串未正确配置");
    }
    if (settings.TwilioSettings == null)
    {
        throw new InvalidOperationException("Twilio相关配置未正确加载");
    }

    builder.Services.AddSingleton(settings);
    builder.Services.AddSingleton(settings.TwilioSettings);
    // 注意你原代码这里写的是ZZZZZ,和配置类定义的ZZZZZZZ键名不一致,这也是个会触发空引用的坑
    var cs = settings.ConnectionStrings.ZZZZZZZ;
    builder.Services.AddDbContextFactory<JTMContext>(opt => opt.UseSqlServer(cs));
    builder.Services.AddDbContext<JTMContext>(opt => opt.UseSqlServer(cs));
}

另外要注意Azure端配置嵌套选项的规则:Azure应用设置是平的键值对结构,不支持像json那样建嵌套节,配置层级用:分隔即可。比如Twilio相关配置不需要建TwilioSettings的嵌套节点,直接在应用设置里添加三个键:

  • TwilioSettings:AccountSid 填对应AccountSid值
  • TwilioSettings:AuthToken 填对应AuthToken值
  • TwilioSettings:From 填对应发信号码值

连接字符串直接在Azure门户的「连接字符串」配置块里添加名称为ZZZZZZZ的项即可,宿主会自动将其绑定到ConnectionStrings:ZZZZZZZ配置路径,不需要额外处理。

原来代码里拼接路径、读取local.settings.json、手动初始化ConfigurationBuilder的逻辑全部删掉就行,宿主已经把所有配置源都加载好了,直接复用即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:09:29