Azure 函数 - 使用 appsettings.json
Azure Functions - using appsettings.json
是否可以在 Azure Functions 中使用 appsettings.json 文件?
这里有环境变量的文档..
..但是我们使用 Octopus 进行部署,并且真的很想控制应用程序设置的版本。
我们已经尝试使用
{
"frameworks": {
"net46": {
"dependencies": {
"Microsoft.Extensions.Configuration": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0"
}
}
}
}
但不断得到
2016-11-23T15:27:03.811 (12,16):错误 CS0012:类型 'Object' 在未引用的程序集中定义。您必须添加对程序集 'System.Runtime, Version=4.0.0.0
的引用
即使能够通过 Octopus supply/update 环境变量也足以满足我们的需求。
请指教
应用程序设置和连接字符串仅支持环境变量。 appsettings.json
不支持。
但是,您可以使用 Azure 资源管理器 (ARM) 模板来配置 Function App 的设置。这里有一个 blog post 更详细地描述了这一点。
对于依赖项,您应该在函数中 use/create project.json。在那里你可以指定你的依赖项。
请检查:
https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp#package-management
例如:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ProjectOxford.Face": "1.1.0"
}
}
}
}
根据您的需要,答案是肯定的! Azure Functions 可以使用 appsettings.json 进行配置。但是当请求函数时,Azure 会执行一些排序顺序。
1º) Azure 将查找您在 .GetEnvironmentVariables("[KEY]" 上使用的 KEYS ) 方法,通过在 Azure Functions 设置中的应用程序设置边栏选项卡上配置的密钥
2º) 如果 Azure 无法通过应用程序设置键找到该配置,那么 Azure 将尝试在您的根文件夹中查找 appsettings.json 文件您正在处理的功能。
3º) 最后,如果 Azure 在应用程序设置和 appsettings.json 文件中都无法找到此密钥,则 Azure 将进行最后一次尝试以查找 web.config对于此文件 appsettings section keys.
感谢您,您可以通过我的 github 存储库中的示例找到这些配置:here and here
希望这些信息对您有所帮助。
根据对配置文件所做的更改,您应该只使用 local.settings.json,因为 appsettings.json 已重命名为 local.settings.json
更改参考:
azure-functions-cli
在 Azure Functions 中,设置存储在 local.settings.json 中(如果您的解决方案中不存在,请创建此文件/名称应与提到的完全一致)。
添加设置文件后,您必须按照下面提到的 运行() 方法对其进行配置,
访问设置时,使用下面
IConfigurationRoot config;
config["fromEmail"];
使用以下命令发布设置
func azure functionapp publish *YourAppName* --publish-local-settings -i
配置源自定义从 Azure Functions 主机版本 2.0.14192.0 和 3.0.14191.0 开始可用。
要指定其他配置源,请在函数应用的 StartUp 中覆盖 ConfigureAppConfiguration 方法 class。
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
public class Startup : FunctionsStartup
{
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder
builder)
{
FunctionsHostBuilderContext context = builder.GetContext();
builder.ConfigurationBuilder
.AddJsonFile(Path.Combine(context.ApplicationRootPath,
"appsettings.json"), optional: true, reloadOnChange: false)
.AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.
{context.EnvironmentName}.json"), optional: true, reloadOnChange: false)
.AddEnvironmentVariables();
}
}
}
//更新csproject中的配置
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
而不是每次都使用配置,您可以在需要时注入选项 class,如下所示。
在 Startup.Configure 方法内部,您可以使用以下代码将 IConfiguration 实例中的值提取到您的自定义类型中:
builder.Services.AddOptions<MyOptions>()
.Configure<IConfiguration>((settings, configuration) =>
{
configuration.GetSection("MyOptions").Bind(settings);
});
函数class:
using System;
using Microsoft.Extensions.Options;
public class HttpTrigger
{
private readonly MyOptions _settings;
public HttpTrigger(IOptions<MyOptions> options)
{
_settings = options.Value;
}
}
我们可以尝试和测试的方法:
- 在您的函数应用程序项目中创建一个 appsettings.json。
- 您需要在继承自 FunctionsStartup class 的项目中添加 Startup.cs class。这将公开一个用于覆盖的方法 Configure(IFunctionsHostBuilder builder)。
- 为了控制自定义级别,我会说扩展 IFunctionsHostBuilder class 假设它是 (IFunctionsHostBuilderExtensions.cs) 并添加一个扩展方法以向其添加新的配置生成器。这给了我们控制我们想要如何在运行时配置 appsettings 设置的好处。
- 完成后,您可以通过传递 appsettings 的整个文件路径或仅传递名称来调用新创建的扩展方法。(您可以在扩展方法中为 appsettings 配置基本路径,以避免在代码)。
- 构建扩展方法后,您将获得可用于注入的服务,即 IConfiguration,可在代码库中的任何地方使用。
- 您还可以为应用程序设置添加多个提供程序,例如 Azure Key Vault、AWS Secret Manager 等。同样,您需要做的就是在 IFunctionsHostBuilderExtensions class 中添加一个扩展方法并调用它们在你的创业公司 class.
- 如果你想让事情更整洁,你可以围绕 IConfiguration 服务实现一个包装器来公开一个 GetSettings(string key) 方法,该方法将 return您希望从 IConfiguration 中的提供程序集中集合获得的设置。
下面是一些代码片段:
/// <summary>
/// Represents the startup class of the function app.
/// </summary>
public class Startup : FunctionsStartup
{
private const string LocalSettingFileGenericName = "appsettings";
private const string LocalSettingFileExtension = "json";
/// <summary>
/// Configures the host builder for the function app.
/// </summary>
/// <param name="builder">The function app host builder.</param>
public override void Configure(IFunctionsHostBuilder builder)
{
try
{
builder.AddConfiguration((configurationBuilder) =>
{
var configuration = typeof(Startup).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>().Configuration;
var configurationFileName = !string.Equals(configuration, "Release")
? $"{LocalSettingFileGenericName}.{configuration.ToLowerInvariant()}.{LocalSettingFileExtension}"
: $"{LocalSettingFileGenericName}.{LocalSettingFileExtension}";
var configurationSource = configurationBuilder
.AddJsonFile(configurationFileName, false, true)
.AddEnvironmentVariables();
var partialConfigurationBuilder = configurationSource.Build();
var keyVaultName = partialConfigurationBuilder.GetSection(ConfigurationKeys.KeyvaultName)?.Value;
return configurationSource
.AddKeyVaultWithManagedIdentity(keyVaultName)
.Build();
});
IFunctionBuilderExtensions.cs
internal static class IFunctionsHostBuilderConfigurationsExtensions
{
private const string keyVaultGenericUri = "https://{0}.vault.azure.net/";
/// <summary>
/// Provides an extension method to add configuration provider.
/// </summary>
/// <param name="builder">The function app host builder.</param>
/// <param name="configBuilderFunc">The delegate to pointing to configuration builder.</param>
/// <returns>The function app host builder</returns>
public static IFunctionsHostBuilder AddConfiguration(
this IFunctionsHostBuilder builder,
Func<IConfigurationBuilder, IConfiguration> configBuilderFunc)
{
var configurationBuilder = builder.GetBaseConfigurationBuilder();
var configuration = configBuilderFunc(configurationBuilder);
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), configuration));
return builder;
}
/// <summary>
/// Provides an extension method to add Azure Key Vault as a configuration provider.
/// </summary>
/// <param name="builder">The configuration builder.</param>
/// <param name="keyvaultName">The azure key vault name.</param>
/// <param name="authenticationClientId">The AAD application clientId.</param>
/// <param name="authenticationClientSecret">The AAD application clientSecret.</param>
/// <returns>The configuration builder.</returns>
public static IConfigurationBuilder AddKeyVaultWithManagedIdentity(
this IConfigurationBuilder builder,
string keyvaultName)
{
if (string.IsNullOrWhiteSpace(keyvaultName))
{
return builder;
}
var serviceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback));
var keyVaultUri = string.Format(keyVaultGenericUri, keyvaultName);
builder.AddAzureKeyVault(
keyVaultUri,
keyVaultClient,
new DefaultKeyVaultSecretManager());
return builder;
}
private static IConfigurationBuilder GetBaseConfigurationBuilder(this IFunctionsHostBuilder builder)
{
var configurationBuilder = new ConfigurationBuilder();
var descriptor = builder.Services.FirstOrDefault(
service => service.ServiceType == typeof(IConfiguration));
if (descriptor?.ImplementationInstance is IConfiguration configRoot)
{
configurationBuilder.AddConfiguration(configRoot);
}
var rootConfigurationBuilder = configurationBuilder.SetBasePath(GetCurrentDirectory());
return rootConfigurationBuilder;
}
private static string GetCurrentDirectory()
{
var currentDirectory = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
return currentDirectory.Replace("bin", "{Your settings directory}");
}
包装器实现示例:
/// <summary>
/// Represents the configuration settings provider class.
/// </summary>
public class ConfigurationSettings : IConfigurationSettings
{
private readonly IConfiguration configurationSource;
/// <summary>
/// Initializes the class of type <see cref="ConfigurationSettings"/>.
/// </summary>
/// <param name="configurationSource">The configuration source.</param>
public ConfigurationSettings(
IConfiguration configurationSource)
{
this.configurationSource = configurationSource;
}
///<inheritdoc/>
public T GetSetting<T>(string key)
{
try
{
if (!configurationSource.GetSection(key).Exists())
{
throw new ConfigurationDoesNotExistException(
$"The configuration with key {key} does not exist in appsetting or key vault.");
}
return (T)Convert.ChangeType(configurationSource.GetSection(key)?.Value, typeof(T));
}
catch (InvalidCastException)
{
throw;
}
catch (Exception)
{
throw;
}
}
}
是否可以在 Azure Functions 中使用 appsettings.json 文件?
这里有环境变量的文档..
..但是我们使用 Octopus 进行部署,并且真的很想控制应用程序设置的版本。
我们已经尝试使用
{
"frameworks": {
"net46": {
"dependencies": {
"Microsoft.Extensions.Configuration": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0"
}
}
}
}
但不断得到
2016-11-23T15:27:03.811 (12,16):错误 CS0012:类型 'Object' 在未引用的程序集中定义。您必须添加对程序集 'System.Runtime, Version=4.0.0.0
的引用即使能够通过 Octopus supply/update 环境变量也足以满足我们的需求。
请指教
应用程序设置和连接字符串仅支持环境变量。 appsettings.json
不支持。
但是,您可以使用 Azure 资源管理器 (ARM) 模板来配置 Function App 的设置。这里有一个 blog post 更详细地描述了这一点。
对于依赖项,您应该在函数中 use/create project.json。在那里你可以指定你的依赖项。 请检查: https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp#package-management
例如:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ProjectOxford.Face": "1.1.0"
}
}
}
}
根据您的需要,答案是肯定的! Azure Functions 可以使用 appsettings.json 进行配置。但是当请求函数时,Azure 会执行一些排序顺序。
1º) Azure 将查找您在 .GetEnvironmentVariables("[KEY]" 上使用的 KEYS ) 方法,通过在 Azure Functions 设置中的应用程序设置边栏选项卡上配置的密钥
2º) 如果 Azure 无法通过应用程序设置键找到该配置,那么 Azure 将尝试在您的根文件夹中查找 appsettings.json 文件您正在处理的功能。
3º) 最后,如果 Azure 在应用程序设置和 appsettings.json 文件中都无法找到此密钥,则 Azure 将进行最后一次尝试以查找 web.config对于此文件 appsettings section keys.
感谢您,您可以通过我的 github 存储库中的示例找到这些配置:here and here
希望这些信息对您有所帮助。
根据对配置文件所做的更改,您应该只使用 local.settings.json,因为 appsettings.json 已重命名为 local.settings.json
更改参考: azure-functions-cli
在 Azure Functions 中,设置存储在 local.settings.json 中(如果您的解决方案中不存在,请创建此文件/名称应与提到的完全一致)。
添加设置文件后,您必须按照下面提到的 运行() 方法对其进行配置,
访问设置时,使用下面
IConfigurationRoot config;
config["fromEmail"];
使用以下命令发布设置
func azure functionapp publish *YourAppName* --publish-local-settings -i
配置源自定义从 Azure Functions 主机版本 2.0.14192.0 和 3.0.14191.0 开始可用。
要指定其他配置源,请在函数应用的 StartUp 中覆盖 ConfigureAppConfiguration 方法 class。
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
public class Startup : FunctionsStartup
{
public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder
builder)
{
FunctionsHostBuilderContext context = builder.GetContext();
builder.ConfigurationBuilder
.AddJsonFile(Path.Combine(context.ApplicationRootPath,
"appsettings.json"), optional: true, reloadOnChange: false)
.AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.
{context.EnvironmentName}.json"), optional: true, reloadOnChange: false)
.AddEnvironmentVariables();
}
}
}
//更新csproject中的配置
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="appsettings">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
而不是每次都使用配置,您可以在需要时注入选项 class,如下所示。 在 Startup.Configure 方法内部,您可以使用以下代码将 IConfiguration 实例中的值提取到您的自定义类型中:
builder.Services.AddOptions<MyOptions>()
.Configure<IConfiguration>((settings, configuration) =>
{
configuration.GetSection("MyOptions").Bind(settings);
});
函数class:
using System;
using Microsoft.Extensions.Options;
public class HttpTrigger
{
private readonly MyOptions _settings;
public HttpTrigger(IOptions<MyOptions> options)
{
_settings = options.Value;
}
}
我们可以尝试和测试的方法:
- 在您的函数应用程序项目中创建一个 appsettings.json。
- 您需要在继承自 FunctionsStartup class 的项目中添加 Startup.cs class。这将公开一个用于覆盖的方法 Configure(IFunctionsHostBuilder builder)。
- 为了控制自定义级别,我会说扩展 IFunctionsHostBuilder class 假设它是 (IFunctionsHostBuilderExtensions.cs) 并添加一个扩展方法以向其添加新的配置生成器。这给了我们控制我们想要如何在运行时配置 appsettings 设置的好处。
- 完成后,您可以通过传递 appsettings 的整个文件路径或仅传递名称来调用新创建的扩展方法。(您可以在扩展方法中为 appsettings 配置基本路径,以避免在代码)。
- 构建扩展方法后,您将获得可用于注入的服务,即 IConfiguration,可在代码库中的任何地方使用。
- 您还可以为应用程序设置添加多个提供程序,例如 Azure Key Vault、AWS Secret Manager 等。同样,您需要做的就是在 IFunctionsHostBuilderExtensions class 中添加一个扩展方法并调用它们在你的创业公司 class.
- 如果你想让事情更整洁,你可以围绕 IConfiguration 服务实现一个包装器来公开一个 GetSettings(string key) 方法,该方法将 return您希望从 IConfiguration 中的提供程序集中集合获得的设置。
下面是一些代码片段:
/// <summary>
/// Represents the startup class of the function app.
/// </summary>
public class Startup : FunctionsStartup
{
private const string LocalSettingFileGenericName = "appsettings";
private const string LocalSettingFileExtension = "json";
/// <summary>
/// Configures the host builder for the function app.
/// </summary>
/// <param name="builder">The function app host builder.</param>
public override void Configure(IFunctionsHostBuilder builder)
{
try
{
builder.AddConfiguration((configurationBuilder) =>
{
var configuration = typeof(Startup).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>().Configuration;
var configurationFileName = !string.Equals(configuration, "Release")
? $"{LocalSettingFileGenericName}.{configuration.ToLowerInvariant()}.{LocalSettingFileExtension}"
: $"{LocalSettingFileGenericName}.{LocalSettingFileExtension}";
var configurationSource = configurationBuilder
.AddJsonFile(configurationFileName, false, true)
.AddEnvironmentVariables();
var partialConfigurationBuilder = configurationSource.Build();
var keyVaultName = partialConfigurationBuilder.GetSection(ConfigurationKeys.KeyvaultName)?.Value;
return configurationSource
.AddKeyVaultWithManagedIdentity(keyVaultName)
.Build();
});
IFunctionBuilderExtensions.cs
internal static class IFunctionsHostBuilderConfigurationsExtensions
{
private const string keyVaultGenericUri = "https://{0}.vault.azure.net/";
/// <summary>
/// Provides an extension method to add configuration provider.
/// </summary>
/// <param name="builder">The function app host builder.</param>
/// <param name="configBuilderFunc">The delegate to pointing to configuration builder.</param>
/// <returns>The function app host builder</returns>
public static IFunctionsHostBuilder AddConfiguration(
this IFunctionsHostBuilder builder,
Func<IConfigurationBuilder, IConfiguration> configBuilderFunc)
{
var configurationBuilder = builder.GetBaseConfigurationBuilder();
var configuration = configBuilderFunc(configurationBuilder);
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), configuration));
return builder;
}
/// <summary>
/// Provides an extension method to add Azure Key Vault as a configuration provider.
/// </summary>
/// <param name="builder">The configuration builder.</param>
/// <param name="keyvaultName">The azure key vault name.</param>
/// <param name="authenticationClientId">The AAD application clientId.</param>
/// <param name="authenticationClientSecret">The AAD application clientSecret.</param>
/// <returns>The configuration builder.</returns>
public static IConfigurationBuilder AddKeyVaultWithManagedIdentity(
this IConfigurationBuilder builder,
string keyvaultName)
{
if (string.IsNullOrWhiteSpace(keyvaultName))
{
return builder;
}
var serviceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback));
var keyVaultUri = string.Format(keyVaultGenericUri, keyvaultName);
builder.AddAzureKeyVault(
keyVaultUri,
keyVaultClient,
new DefaultKeyVaultSecretManager());
return builder;
}
private static IConfigurationBuilder GetBaseConfigurationBuilder(this IFunctionsHostBuilder builder)
{
var configurationBuilder = new ConfigurationBuilder();
var descriptor = builder.Services.FirstOrDefault(
service => service.ServiceType == typeof(IConfiguration));
if (descriptor?.ImplementationInstance is IConfiguration configRoot)
{
configurationBuilder.AddConfiguration(configRoot);
}
var rootConfigurationBuilder = configurationBuilder.SetBasePath(GetCurrentDirectory());
return rootConfigurationBuilder;
}
private static string GetCurrentDirectory()
{
var currentDirectory = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
return currentDirectory.Replace("bin", "{Your settings directory}");
}
包装器实现示例:
/// <summary>
/// Represents the configuration settings provider class.
/// </summary>
public class ConfigurationSettings : IConfigurationSettings
{
private readonly IConfiguration configurationSource;
/// <summary>
/// Initializes the class of type <see cref="ConfigurationSettings"/>.
/// </summary>
/// <param name="configurationSource">The configuration source.</param>
public ConfigurationSettings(
IConfiguration configurationSource)
{
this.configurationSource = configurationSource;
}
///<inheritdoc/>
public T GetSetting<T>(string key)
{
try
{
if (!configurationSource.GetSection(key).Exists())
{
throw new ConfigurationDoesNotExistException(
$"The configuration with key {key} does not exist in appsetting or key vault.");
}
return (T)Convert.ChangeType(configurationSource.GetSection(key)?.Value, typeof(T));
}
catch (InvalidCastException)
{
throw;
}
catch (Exception)
{
throw;
}
}
}