我目前使用ServiceBusTrigger绑定具有azure功能
[ServiceBusTrigger("%TopicName%", "%SubscripionName%", Connection = "MyConnection")]
string catclogueEventMsgs, ILogger log, ExecutionContext context)
使用此local.settings.json文件
"Values": {
…
"MyConnection": "Endpoint=sb://testxxxxxxxxxxxxxxxxxx
"SubscriptionName": "testsubscriptionName"
"TopicName": "testtopicName",
}
我该如何在appsettings.json文件中表示它。会像下面吗?
"Values": {
"MyConnection": "Endpoint=sb://testxxxxxxxxxxxxxxxxxx
"SubscriptionName": "testsubscriptionName"
"TopicName": "testtopicName",
}
我可以像下面这样使用“ MySubs”对象代替我的“ Values”对象吗?
"MySubs": {
"MyConnection": "Endpoint=sb://testxxxxxxxxxxxxxxxxxx
"SubscriptionName": "testsubscriptionName"
"TopicName": "testtopicName",
}
如果可以使用上述设置,我该如何在ServiceBusTrigger绑定中表示它?我会改成这个吗?
[ServiceBusTrigger("%MySubs.TopicName%", "%MySubs.SubscripionName%", Connection = "MySubs.MyConnection")]
string catclogueEventMsgs, ILogger log, ExecutionContext context)
答案 0 :(得分:2)
恐怕是不可能的。根据设计,本地Azure Function在Values
文件中读取local.settings.json
来检索与绑定相关的设置。
检查local.settings.json中Values
的描述。
在本地运行时使用的应用程序设置和连接字符串的集合。这些值与Azure中的功能应用程序中的应用程序设置相对应,例如AzureWebJobsStorage和AzureWebJobsDashboard。
许多触发器和绑定具有引用连接字符串应用程序设置的属性,例如Blob存储触发器的Connection。对于此类属性,您需要在Values数组中定义的应用程序设置。
对于生产环境(即在Azure网站上),我们只能依靠Application settings来检索与绑定相关的设置。
答案 1 :(得分:1)
您确实可以按以下方式读取Values
数组之外的设置:
public class WeatherApiConfig
{
public string WeatherApiUrl { get; set; }
public string WeatherApiKey { get; set; }
}
Azure Functions V2的新增功能we have an appropriate way to handle DI,如下所示:
[assembly: FunctionsStartup(typeof(BlazingDemo.Api.Startup))]
namespace BlazingDemo.Api
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
var apiConfig = new WeatherApiConfig();
config.GetSection("WeatherApiConfig").Bind(apiConfig);
builder.Services.AddSingleton(apiConfig);
builder.Services.AddHttpClient();
}
}
}
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
},
"WeatherApiConfig": {
"WeatherApiUrl": "http://api.openweathermap.org/data/2.5/weather",
"WeatherApiKey": "**removed**"
}
}
注意:对我来说,关键是在
.SetBasePath(Directory.GetCurrentDirectory())
中添加Startup.cs
,因为没有它找不到文件。
在生产环境中,我使用功能应用程序的Application Settings
部分来配置这两个属性,如下所示:
答案 2 :(得分:0)
看起来 Jason 和 Oneil/Liam 的混合体是正确的。
据我所知,在函数的名称/声明/定义中,它必须来自开发时的local.settings.json,并像“%TheQueueName%”一样引用,然后在Function中输入配置 -> Azure 应用程序设置。
在实际函数本身中,您可以通过 Startup.cs 利用 json 文件注入,然后将值包含在函数本身中。
这值得一个完全独立的博客文章(并且有类似的,但没有提到的那么复杂的设置,但这是我在一年多后所做的和想出来的,并且效果非常好。
文件设置:
配置设置:Startup.cs
(即使它说 /home/site/wwwroot - 文件基于项目的根目录,发布时将是根目录)
public override void Configure(IFunctionsHostBuilder builder)
{
var currentDirectory = "/home/site/wwwroot";
var config = new ConfigurationBuilder()
.SetBasePath(currentDirectory)
.AddJsonFile("local.settings.json", optional: false, reloadOnChange: true)
.AddJsonFile("Config/xyz.settings.json", optional: false, reloadOnChange: true)
.AddJsonFile("Config/xyz.settings.dev.json", optional: true, reloadOnChange: true)
.AddJsonFile("Config/secret.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
builder.Services.Configure<XyzSettings>(config.GetSection("XyzSettings"));
它有什么作用以及它是如何工作的:
说到秘密:
本地机密可以存储在 secrets.json 中,只要它们未设置为发布即可。
在 Azure 中,建议将值存储在可访问 Azure Key Vault 的 Function App Settings 中。
它的配置方式非常棒。您在 Function App Settings 中所做的就是将变量命名为它在设置中的名称,例如 XyzSettings:SettingName,然后引用 Key Vault 中的位置,如下所示:
@Microsoft.KeyVault(SecretUri=https://yourvalutname.vault.azure.net/secrets/secret-name/auto-generated-keyvaultguid)
函数文件: (以队列触发器为例,但操作方式相同)
namespace Xyz.Functions
{
public class Azure_Queue_Add_Xyz
{
private readonly XyzSettings _xyzSettings = null;
public Azure_Queue_Add_Xyz(IOptions<AzureSettings> azure_settings)
{
_azureSettings = azure_settings.Value;
}
[FunctionName("Azure_Queue_Add_Xyz")]
public void Run(
[HttpTrigger(AuthorizationLevel.Function, "post",
Route = "HttpTrigger/Azure_Queue_Add_Xyz")] xyzConfig input,
[Queue("%TheQueueName%"), StorageAccount("StorageAccount")] ICollector<string> msgOutput,
ILogger logger,
ExecutionContext context)
{
logger.LogError("{0} is processing a request", context.FunctionName);
logger.LogError("{0} - Queue: {1}", context.FunctionName, _xyzSettings.TheQueueName);
logger.LogError("{0} - CloudQueueMessage: {1}", context.FunctionName, JsonConvert.SerializeObject(input));
msgOutput.Add(JsonConvert.SerializeObject(input));
}
}
}
答案 3 :(得分:0)
这是如何为 .NET 5 做这件事,例如一些覆盖秘密的例子:
Kotobee 设置:
public class KotobeeSettings
{
public string BaseUrl { get; set; }
public string SerialNumber { get; set; }
}
Program.cs:
public class Program
{
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureAppConfiguration((hostContext, builder) =>
{
builder.AddJsonFile("local.settings.json");
//This will override any values added to local.settings.json if you wish to check in this file - Recommended approach for keeping secrets in dev is this though:
//https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#register-the-user-secrets-configuration-source
//builder.AddJsonFile("secrets.settings.json");
if (hostContext.HostingEnvironment.IsDevelopment())
{
builder.AddUserSecrets<Program>();
}
})
.ConfigureServices((hostContext, services) =>
{
var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings:DefaultConnection");
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
connectionString,
sqlServerOptions => sqlServerOptions.CommandTimeout(600)));
services.AddHttpClient();
var configuration = hostContext.Configuration;
var settings = new KotobeeSettings();
configuration.Bind("KotobeeSettings", settings);
services.AddSingleton(settings);
services.AddTransient<KotobeeClient>();
services.AddTransient<OrderRowService>();
})
.Build();
CreateDbAndApplyMigrations(host);
host.Run();
}
private static void CreateDbAndApplyMigrations(IHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var context = services.GetRequiredService<ApplicationDbContext>();
context.Database.Migrate();
}
}
示例 local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
},
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=Project.Ebook;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"KotobeeSettings": {
"BaseUrl": "BaseURL",
"SerialNumber": "--SECRET--"
}
}
例如secrets.settings.json 和secrets.json:
{
"KotobeeSettings": {
"SerialNumber": "123"
}
}
像这样注入的设置:
public class TimerTrigger
{
private readonly OrderRowService _orderRowService;
private readonly KotobeeSettings _settings;
public TimerTrigger(OrderRowService orderRowService, KotobeeSettings settings)
{
_orderRowService = orderRowService;
_settings = settings;
}
[Function("TimerTrigger")]
public async Task RunAsync([TimerTrigger("0 */1 * * * *")] MyInfo myTimer, FunctionContext context)
{
var baseUrl = _settings.BaseUrl;
var logger = context.GetLogger("TimerTrigger");
logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus?.Next}");
}
}
public class MyInfo
{
public MyScheduleStatus ScheduleStatus { get; set; }
public bool IsPastDue { get; set; }
}
public class MyScheduleStatus
{
public DateTime Last { get; set; }
public DateTime Next { get; set; }
public DateTime LastUpdated { get; set; }
}