azure - 在 FunctionsStartup 中使用 ConfigurationBuilder

标签 azure azure-functions

我有一个 Azure 函数,我正在使用 DI 系统来注册一些类型;例如:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services
            .AddTransient<IMyInterface, MyClass>()
    . . . etc

但是,我还要从我的环境设置中注册一些数据。在函数内部,我可以得到 ExecutionContext ,所以我可以这样做:
IConfiguration config = new ConfigurationBuilder()
   .SetBasePath(context.FunctionAppDirectory)
   .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
   .AddEnvironmentVariables()
   .Build();

但是,在 FunctionsStartup 中,我无权访问 ExecutionContext .有没有办法可以从 FunctionsStartup 类中获取 ExecutionContext ,或者另一种确定当前运行目录的方法,以便我可以设置基本路径?

最佳答案

虽然对这个问题的检查答案是正确的,但我认为它缺乏关于原因的深度。您应该知道的第一件事是,在幕后,Azure 函数使用相同的 配置生成器 在 ASP.NET Core 应用程序中找到,但具有一组不同的提供程序。与 ASP.NET Core 的文档非常详细 (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) 不同,Azure Functions 并非如此。
要了解这组提供程序,您可以将以下代码行放入 配置(IFunctionsHostBuilder 构建器)您的方法 功能启动类(class),

var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
在命令后放置一个调试断点,在 Debug模式下执行您的函数并在配置变量上执行快速观察...(右键单击变量名称以选择快速观察...)。
深入代码执行的结果是以下提供程序列表。
Microsoft.Extensions.Configuration.ChainedConfigurationProvider
MemoryConfigurationProvider
HostJsonFileConfigurationProvider
JsonConfigurationProvider for 'appsettings.json' (Optional)
EnvironmentVariablesConfigurationProvider
MemoryConfigurationProvider
ChainedConfigurationProvider 添加一个现有的 IConfiguration 作为来源。在默认配置情况下,添加主机配置并将其设置为应用程序配置的第一个源。
第一内存配置提供程序 添加键/值 {[AzureWebJobsConfigurationSection, AzureFunctionsJobHost]} .至少它在开发环境中是这样做的。在我写这篇文章的时候,我找不到关于这个目的的文档 内存配置提供程序 AzureWebJobs 配置部分 .
HostJsonFileConfigurationProvider 是另一个隐藏的无证提供者,但是在查看 上的文档时host.json ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json ) 它似乎负责提取此元数据。
JsonConfigurationProvider appsettings.json 似乎与 ASP.NET Core 使用 有明显的相关性。 appsettings.json 除了一件事它不起作用。经过一番调查,我发现 来源 文件提供程序 没有设置为文件所在的应用程序根文件夹,而是一些模糊的 AppData 文件夹(C:\Users%USERNANE%\AppData\Local\AzureFunctionsTools\Releases\3.15.0\cli_x64)。去钓鱼。
EnvironmentVariablesConfigurationProvider 加载环境变量键值对。
第二个内存配置提供程序 添加键/值 {[AzureFunctionsJobHost:logging:console:isEnabled, false]} .至少它在开发环境中是这样做的。同样,在我写这篇文章的时候,我找不到关于这个 目的的文档。内存配置提供程序 AzureFunctionsJobHost .
现在需要指出的有趣的事情是配置中没有任何地方提到 local.settings.json .那是因为 local.settings.json 不是 的一部分配置生成器 过程。而是 local.settings.json 是 Azure Functions Core Tools 的一部分,可让您在本地计算机 ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local ) 上开发和测试您的函数。 Azure 函数核心工具仅关注特定部分和键/值,例如 IsEncrypted , 连接字符串 文档中定义的部分等( https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file )。这些键/值发生的事情也是独一无二的。例如, 中的键/值值 部分作为变量插入到环境中。大多数开发人员甚至没有注意到 local.settings.json 默认设置为被 Git 忽略,如果您从开发环境中删除存储库只是为了在将来恢复它,这也会导致问题。 ASP.NET Core 已使用应用程序 secret ( https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets ) 修复的问题。
那么,如果我们使用 创建我们自己的配置会发生什么?配置生成器 正如原始问题中所建议的
IConfiguration config = new ConfigurationBuilder()
   .SetBasePath(context.FunctionAppDirectory)
   .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
   .AddEnvironmentVariables()
   .Build();
或使用其他答案之一中显示的示例?
ExecutionContextOptions executionContextOptions = builder.Services.BuildServiceProvider().GetService<IOptions<ExecutionContextOptions>>().Value;

IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
    .SetBasePath(executionContextOptions.AppDirectory)
    .AddEnvironmentVariables()
    .AddJsonFile("appsettings.json", false)
    .AddJsonFile("local.settings.json", true)
    .AddUserSecrets(Assembly.GetExecutingAssembly(), true);
以下只是这两个示例的一些问题。
  • 第二个示例的顺序不正确,因为 AddEnvironmentVariables 应该放在最后。
  • 这两个示例都没有提到需要以下代码行。
    项目 list builder.Services.AddSingleton<IConfiguration>(configurationBuilder.Build());没有这一行,配置只存在于 配置(IFunctionsHostBuilder 构建器)您的方法 功能启动类(class)。但是,使用该行替换 Azure Function 内部构建的配置。这不一定是一件好事,因为您无法替换像 这样的提供商。 HostJsonFileConfigurationProvider .
  • 阅读 local.settings.json 文件( .AddJsonFile("appsettings.json") )不会将键/值对放在 中值 按预期将部分作为单独的键/值对进入配置,而是将它们分组在 下值 部分。换句话说,例如,如果您想访问 {["AzureWebJobsStorage": ""]} 您可以使用命令 configuration.GetValue("Values:AzureWebJobsStorage") .问题是 Azure 期望通过 key 名称 访问它。 “AzureWebJobsStorage” .更有趣的是,因为 local.settings.json 从来不是 的一部分。配置生成器 这是多余的,因为 Azure Functions Core Tools 已经将这些值放入环境中。这样做的唯一作用是允许您访问未定义为 一部分的部分和键/值。 local.settings.json ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file )。但是为什么要从不会复制到生产代码中的文件中提取配置值呢?

  • 所有这些都为我们提供了一种更好的方法来影响对配置的更改,而不会破坏 Azure Function 的默认配置构建,即覆盖 配置应用配置 您的 中的方法功能启动类( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources )。
    以下示例通过添加用户 secret 使文档中提供的示例更进一步。
    public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
    {
        FunctionsHostBuilderContext context = builder.GetContext();
    
        builder.ConfigurationBuilder
            .SetBasePath(context.ApplicationRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
            .AddJsonFile($"appsettings.{context.EnvironmentName}.json", optional: true, reloadOnChange: false)
            .AddUserSecrets(Assembly.GetExecutingAssembly(), true, true)
            .AddEnvironmentVariables();
    }
    
    默认情况下,配置文件如 appsettings.json 不会自动复制到 Azure Function 输出文件夹。请务必查看文档 ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources ) 以修改您的 .csproj 文件。另请注意,由于该方法附加现有提供程序的方式,必须始终以 结尾。 .AddEnvironmentVariables() .

    关于azure - 在 FunctionsStartup 中使用 ConfigurationBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57360238/

    相关文章:

    Azure 存储同步机制

    c# - 提高 Linq SQL 查询性能

    Azure管道正在运行旧版本文件(上次提交之前)

    Azure 逻辑应用 FTP 获取文件内容失败

    Azure 存储队列最大并发客户端数

    azure - 是否可以将 AzureAppConfiguration 与 Azure Function ServiceBusTrigger 一起使用

    azure - 如何查看azure函数的最后部署日期?

    azure - 按逻辑分区缩放 Azure Functions 的 CosmosDB 绑定(bind)

    c# - 找不到“用户密码凭据”

    powershell - 启动/停止特定订阅下的所有虚拟机