Мой минимальный веб-API использует Конфигурацию приложений Azure для хранения нескольких параметров конфигурации.
Теперь мне нужно получить некоторые значения из этих конфигураций перед .Build() веб-приложением, и я не могу найти способ получить свои настройки, кроме использования BuildServiceProvider.
var builder = WebApplication.CreateBuilder(args);
const string JSON = "json";
var appSettingsKey = CONSTANTS.APP.SETTINGS.APPSETTINGS.ToLower();
builder.Configuration.AddJsonFile($"{appSettingsKey}.{JSON}", optional: true, reloadOnChange: true);
builder.Configuration.AddJsonFile($"{appSettingsKey}.{builder.Environment.EnvironmentName}.{JSON}", optional: true, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();
builder.Services.Configure<Settings>(builder.Configuration.GetSection(CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_PREFIX));
builder.Configuration.AddAzureAppConfiguration(options => options.Connect(builder.Configuration.GetConnectionString(CONSTANTS.APP.SETTINGS.APP_CONFIGURATION_CONNECTION_STRING))
.Select(CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_KEY_FILTER, CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_LABEL_FILTER)
.ConfigureRefresh(refresh => refresh.Register($"{CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_PREFIX}:{CONSTANTS.APP.SETTINGS.SENTINEL_KEY}", refreshAll: true))
.UseFeatureFlags());
var buildServiceProvider = builder.Services.BuildServiceProvider();
var settings = (buildServiceProvider.GetRequiredService<IOptions<Settings>>() ?? null) ?? throw new InvalidOperationException();
builder.Host.UseSerilog((hostBuilderContext, services, configuration) =>
{
configuration.ConfigureLogging(CONSTANTS.CLUSTER.EQUINOX.ToUpper());
configuration.AddApplicationInsightsLogging(services, hostBuilderContext.Configuration, settings.Value);
});
builder.UseOrleans(settings);
builder.AddServices(settings);
var app = builder.Build();
Теперь я знаю, что вызов BuildServiceProvider из кода приложения приводит к в дополнительной копии одноэлементных служб, но поскольку мне нужно зарегистрировать некоторые службы, которым нужны эти настройки, например ApplicationInsights для Serilog, я не знаю, как это сделать.
Как правильно это сделать?





Вы можете использовать метод расширения ConfigurationBinder.Get, без необходимости создавать поставщика услуг. Что-то в этом роде:
// after setting up all configuration sources
var section = builder.Configuration.GetSection(CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_PREFIX);
var settings = section.Get<Settings>();
// use settings
P.S.
AFAIK AddJsonFile и AddEnvironmentVariables добавляются по умолчанию для веб-приложений, поэтому вы можете пропустить их.
Один из способов обойти эту проблему, если вы размещаете свое приложение в Службе приложений Azure, — использовать параметр приложения на основе AppConfig в вашей Службе приложений. По сути, это заставляет веб-приложение предоставлять значение из Azure AppConfig в качестве переменной среды — таким образом, оно будет доступно при запуске, и вы получите к нему доступ напрямую, используя Environment.GetEnvironmentVariable("myappservicekey"). У вас уже есть вызов builder.Configuration.AddEnvironmentVariables(), поэтому вы также должны иметь к нему доступ, используя обычные шаблоны конфигурации, которые вы обычно используете и для всего остального.
Предполагая, что у вас есть AppConfig с URL-адресом «https://myappconfig.azconfig.io» и определенным ключом конфигурации «myappconfigkey», возможно, с меткой «mylabel», вам нужно сделать две вещи:
App Configuration Data Reader управляемому удостоверению вашего веб-приложения. Это позволит конфигурации вашего веб-приложения читать эти настройки — вероятно, вы уже настроили эту настройку, так как вам все равно нужно, чтобы ваше приложение читало оттуда.@Microsoft.AppConfiguration(Endpoint=https://myappconfig.azconfig.io; Key=myappconfigkey). Если вы также использовали ярлык, укажите значение @Microsoft.AppConfiguration(Endpoint=https://myappconfig.azconfig.io; Key=myappconfigkey; Label=mylabel).Если вы используете метки и слоты развертывания, вы можете сделать этот параметр настройкой слота развертывания, чтобы иметь разные метки для каждого слота.
Сохраните изменения, и вы должны увидеть что-то вроде этого: снимок экрана настроенной переменной среды Azure App Service, поддерживаемой AppConfig. Если у вас есть зеленая галочка рядом с «Конфигурация приложения», все готово. Если у вас нет зеленой галочки, либо ваши разрешения, либо ваша ссылка неверны.
Вы не увидите фактическое значение параметра AppConfig на портале Azure, а увидите только ссылку на соответствующий ключ AppConfig. Это работает во многом так же, как переменные среды AppService, поддерживаемые KeyVault, только с использованием @Microsoft.AppConfiguration вместо @Microsoft.KeyVault. Ваше приложение получит фактическое значение во время выполнения.
Дополнительную информацию см. https://learn.microsoft.com/en-us/azure/app-service/app-service-configuration-references.
Вы уже получаете доступ к builder.Configuration до вызова build(). Почему это должно быть иначе?