Конфигурация в .NET Core

Авторы: Рик Андерсон (Rick Anderson) и Кирк Ларкин (Kirk Larkin)

Примечание.

Это не последняя версия этой статьи. Сведения о текущем выпуске см. в ASP.NET версии Core 8.0 этой статьи.

Настройка приложения в ASP.NET Core выполняется с помощью одного или нескольких поставщиков конфигурации. Поставщики конфигурации получают данные конфигурации в парах "ключ-значение" из различных источников:

  • файлов параметров, таких как appsettings.json;
  • Переменные среды
  • Azure Key Vault
  • Настройка приложения Azure
  • Аргументы командной строки
  • пользовательские поставщики, установленные или созданные;
  • справочных файлов;
  • объектов .NET в памяти;

В этой статье приведены сведения о конфигурации в ASP.NET Core. Сведения об использовании конфигурации в консольных приложениях см. в статье Конфигурация .NET.

Конфигурация приложения и узла

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Шаблоны ASP.NET Core создают объект WebApplicationBuilder, содержащий узел. Хотя определенные настройки доступны в поставщиках конфигурации и узла, и приложения, как правило, нужно использовать конфигурацию узла только для необходимых ему настроек.

Конфигурация приложения имеет наивысший приоритет и описана подробно в следующем разделе. Конфигурация узла вторична по отношению к конфигурации приложения, и она описана в этой статье.

Источники конфигурации приложения по умолчанию

Веб-приложения ASP.NET Core, созданные с помощью dotnet new или Visual Studio, создают следующий код:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder инициализирует новый экземпляр класса WebApplicationBuilder с предварительно настроенными значениями по умолчанию. Инициализированный экземпляр WebApplicationBuilder (builder) содержит конфигурацию по умолчанию для приложения с настройками в следующем порядке, от наиболее к наименее приоритетным:

  1. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  2. Переменные среды без префикса, использующие соответствующий поставщик конфигурации.
  3. секреты пользователя, когда приложение выполняется в среде Development;
  4. appsettings.{Environment}.json с использованием поставщика конфигурации JSON. Например, appsettings.Production.json и appsettings.Development.json.
  5. appsettings.json с использованием поставщика конфигурации JSON.
  6. Откат к конфигурации узла, описанной в следующем разделе.

Источники конфигурации узла по умолчанию

В следующем списке содержатся источники конфигурации узла по умолчанию от самого высокого до низкого приоритета для WebApplicationBuilder:

  1. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  2. Переменные среды с префиксом DOTNET_, использующие поставщик конфигурации переменных среды.
  3. Переменные среды с префиксом ASPNETCORE_, использующие поставщик конфигурации переменных среды.

Для универсального узла .NET и веб-узла по умолчанию источники конфигурации узла по умолчанию от самого высокого до низкого приоритета:

  1. Переменные среды с префиксом ASPNETCORE_, использующие поставщик конфигурации переменных среды.
  2. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  3. Переменные среды с префиксом DOTNET_, использующие поставщик конфигурации переменных среды.

Если значение задано в конфигурации и узла, и приложения, то используется конфигурация приложения.

Переменные узла

Следующие переменные фиксируются на ранних этапах при инициализации построителей узлов и не затрагиваются конфигурацией приложения:

Все остальные параметры узла считываются не из конфигурации узла, а из конфигурации приложения.

URLS — один из множества стандартных параметров узла, не относящийся к начальной загрузке. Как и все параметры узла, не приведенные в списке выше, URLS считывается на более позднем этапе из конфигурации приложения. Конфигурация узла используется как страховочный вариант для конфигурации приложения, поэтому можно задать URLS в первой, но это будет переопределено любым источником в конфигурации приложения, например appsettings.json.

Подробнее см. раздел Изменение корневого каталога содержимого, имени приложения и среды, а также Изменение корневой папки содержимого, имени приложения и среды через переменные среды или командную строку.

Остальные разделы этой статьи относятся к конфигурации приложения.

Поставщики конфигурации приложения

В следующем коде отображаются включенные поставщики конфигурации в том порядке, в котором они были добавлены:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "\n";
        }

        return Content(str);
    }
}

В приведенном выше списке источников конфигурации по умолчанию от наиболее к наименее приоритетным поставщики отображаются в порядке, обратному тому, в котором они добавляются в создаваемое из шаблона приложение. Например, поставщик конфигурации JSON добавляется перед поставщиком конфигурации командной строки.

Поставщики конфигурации, добавляемые позже, имеют больший приоритет и переопределяют предыдущие параметры ключей. Например, если MyKey задан в appsettings.json и в среде, используется значение среды. При использовании поставщиков конфигурации по умолчанию поставщик конфигурации командной строки переопределяет остальных поставщиков.

Дополнительные сведения о CreateBuilder см. в разделе Параметры сборщика по умолчанию.

appsettings.json

Рассмотрим следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

JsonConfigurationProvider по умолчанию загружает конфигурацию в следующем порядке:

  1. appsettings.json
  2. appsettings.{Environment}.json: например, файлы appsettings.Production.json и appsettings.Development.json. Версия среды файла загружается на IHostingEnvironment.EnvironmentNameоснове . Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Значения appsettings.{Environment}.json переопределяют ключи в файле appsettings.json. Например, по умолчанию:

  • В среде разработки конфигурация appsettings.Development.json переопределяет значения в файле appsettings.json.
  • В производственной среде конфигурация appsettings.Production.json переопределяет значения в файле appsettings.json. Например, при развертывании приложения в Azure.

Если необходимо гарантировать значение конфигурации, см. раздел о GetValue. Предыдущий пример поддерживает только считывание строк и не поддерживает значение по умолчанию.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Комментарии в appsettings.json

Примечания и appsettings.jsonappsettings.{Environment}.json файлы поддерживаются с помощью комментариев в стиле JavaScript или C#.

Привязка иерархических данных конфигурации с помощью шаблона параметров

Предпочтительный способ чтения связанных значений конфигурации — использование шаблона параметров. Например, чтобы считать следующие значения конфигурации:

  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

Создайте следующий класс PositionOptions:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

Класс параметров:

  • Должен быть неабстрактным с открытым конструктором без параметров.
  • Все открытые свойства чтения и записи типа привязаны.
  • Поля не привязаны. В приведенном выше коде свойство Position не привязано. Поле Position используется так, что строку "Position" не требуется жестко кодировать в приложении при привязке класса к поставщику конфигурации.

Следующий код:

  • Вызывает ConfigurationBinder.Bind для привязки класса PositionOptions к разделу Position.
  • Отображает данные конфигурации Position.
public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

    public Test22Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

ConfigurationBinder.Get<T> привязывает и возвращает указанный тип. Метод ConfigurationBinder.Get<T> может быть более удобным, чем ConfigurationBinder.Bind. В приведенном ниже примере кода демонстрируются способы использования ConfigurationBinder.Get<T> с классом PositionOptions:

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions? positionOptions { get; private set; }

    public Test21Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

Альтернативный подход при использовании шаблона параметров — привязать раздел Position и добавить его в контейнер службы внедрения зависимостей. В следующем коде PositionOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

С помощью приведенного выше кода следующий код считывает параметры расположения:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} \n" +
                       $"Name: {_options.Name}");
    }
}

Приведенном выше кода изменения в файле конфигурации JSON, внесенные после запуска приложения, не считываются. Чтобы считать изменения после запуска приложения, используйте IOptionsSnapshot.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Сведения о добавлении дополнительных файлов конфигурации JSON см. в разделе Поставщик конфигурации JSON этого документа.

Объединение коллекций служб

Рассмотрим следующий код, который регистрирует службы и настраивает параметры:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

builder.Services.AddScoped<IMyDependency, MyDependency>();
builder.Services.AddScoped<IMyDependency2, MyDependency2>();

var app = builder.Build();

Связанные группы регистраций можно переместить в метод расширения для регистрации служб. Например, службы конфигурации добавляются в следующий класс:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

Остальные службы регистрируются в аналогичном классе. Следующий код использует новые методы расширения для регистрации служб:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

Примечание. Каждый services.Add{GROUP_NAME} метод расширения добавляет и потенциально настраивает службы. Например, AddControllersWithViews добавляет контроллеры MVC служб с необходимыми представлениями, а AddRazorPages — службы, требуемые для работы Razor Pages.

Безопасность и секреты пользователей

Рекомендации по данным конфигурации:

  • Никогда не храните пароли или другие конфиденциальные данные в коде поставщика конфигурации или в файлах конфигурации обычного текста. Хранить секреты во время разработки можно с помощью диспетчера секретов.
  • Не используйте секреты рабочей среды в средах разработки и тестирования.
  • Указывайте секреты вне проекта, чтобы их нельзя было случайно зафиксировать в репозитории с исходным кодом.

По умолчанию источник конфигурации пользовательских секретов регистрируется после источников конфигурации JSON. Таким образом, ключи секретов пользователя имеют приоритет над ключами в appsettings.json и appsettings.{Environment}.json.

Дополнительные сведения о хранении паролей или других конфиденциальных данных:

В Azure Key Vault безопасно хранятся секреты приложений ASP.NET Core. Дополнительные сведения см. в статье Поставщик конфигурации Azure Key Vault в ASP.NET Core.

Переменные среды без префикса

К переменным среды без префикса относятся те, что не имеют префикса ASPNETCORE_ или DOTNET_. Для примера можно привести набор шаблонов веб-приложения ASP.NET Core "ASPNETCORE_ENVIRONMENT": "Development" в launchSettings.json. Дополнительные сведения о переменных среды ASPNETCORE_ и DOTNET_:

При использовании конфигурации по умолчаниюEnvironmentVariablesConfigurationProvider загружает конфигурацию из пар "ключ — значение" в переменных среды после чтения appsettings.json, appsettings.{Environment}.json и секретов пользователя. Поэтому значения ключей, считанные из среды, переопределяют значения, считанные из appsettings.json, appsettings.{Environment}.json и секретов пользователя.

Разделитель : не работает с иерархическими ключами переменных среды на всех платформах. __ (двойной символ подчеркивания):

  • Поддерживается всеми платформами. Например, разделитель : не поддерживается Bash, а __ — поддерживается.
  • Автоматически заменяется на :

Следующие команды set:

set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Предыдущие параметры среды:

  • Задаются только в процессах, запускаемых из командного окна, в котором они были установлены.
  • Не будут считываться браузерами, запущенными в Visual Studio.

Следующие команды setx можно использовать для задания ключей и значений среды в Windows. В отличие от set, параметры setx сохраняются. /M задает переменную в системной среде. Если параметр /M не используется, задается переменная среды пользователя.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Чтобы проверить, что предыдущие команды переопределяют appsettings.json и appsettings.{Environment}.json:

  • С помощью Visual Studio: выход и перезапуск Visual Studio.
  • С помощью интерфейса командной строки: запустите новое командное окно и введите dotnet run.

Вызовите AddEnvironmentVariables со строкой, чтобы указать префикс для переменных среды:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

В предыдущем коде:

Префикс отделяется при создании пары конфигурации "ключ-значение".

Следующие команды проверяют пользовательский префикс:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

Конфигурация по умолчанию загружает переменные среды и аргументы командной строки с префиксом DOTNET_ и ASPNETCORE_. Префиксы DOTNET_ и ASPNETCORE_ используются ASP.NET Core для конфигурации узла и приложения, но не для конфигурации пользователя. Дополнительные сведения о конфигурации узла и приложения см. в разделе Универсальный узел .NET.

В Службе приложений Azure выберите Новый параметр приложения на странице Параметры > Конфигурация. Параметры приложения Службы приложений Azure:

  • Шифруются, когда они неактивны, и передаются по зашифрованному каналу.
  • Предоставляются как переменные среды.

Дополнительные сведения см. в разделе Приложения Azure. Переопределение конфигурации приложения с помощью портала Azure.

Сведения о строках подключения к базе данных Azure см. в разделе Префиксы строк подключения.

Именование переменных среды

Имена переменных среды отражают структуру файла appsettings.json. Каждый элемент в иерархии отделяется двойным символом подчеркивания (предпочтительно) или двоеточием. Если структура элемента включает массив, индекс массива должен рассматриваться как дополнительное имя элемента в этом пути. Рассмотрим следующий файл appsettings.json и его эквивалентные значения, представленные в виде переменных среды:

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

Переменные среды

setx SmtpServer smtp.example.com
setx Logging__0__Name ToEmail
setx Logging__0__Level Critical
setx Logging__0__Args__FromAddress MySystem@example.com
setx Logging__0__Args__ToAddress SRE@example.com
setx Logging__1__Name ToConsole
setx Logging__1__Level Information

Переменные среды, заданные в созданном файле launchSettings.json

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде. Например, веб-шаблоны ASP.NET Core создают launchSettings.json файл, который задает конфигурацию конечной точки следующим образом:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

При настройке applicationUrl устанавливается переменная среды ASPNETCORE_URLS и переопределяются значения, заданные в среде.

Экранирование переменных среды в Linux

В Linux значения переменных среды URL-адресов нужно экранировать, чтобы их можно было проанализировать с помощью systemd. Используйте средство Linux systemd-escape, которое приостанавливает http:--localhost:5001.

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

Отображение переменных среды

Следующий код позволяет отобразить переменные среды и значения при запуске приложения, что может быть полезно при отладке параметров среды:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

Командная строка

При использовании конфигурации по умолчаниюCommandLineConfigurationProvider загружает конфигурацию из пар "ключ-значение" аргументов командной строки после следующих источников конфигурации:

По умолчанию значения конфигурации, заданные для значений конфигурации переопределения в командной строке, задаются для всех остальных поставщиков конфигурации.

Аргументы командной строки

Следующая команда задает ключи и значения с помощью =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью /:

dotnet run /MyKey "Using /" /Position:Title=Cmd /Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью --:

dotnet run --MyKey "Using --" --Position:Title=Cmd --Position:Name=Cmd_Rick

Значение ключа:

  • Должно соответствовать =, или ключ должен иметь префикс -- или /, когда значение следует за пробелом.
  • Является обязательным, если используется параметр =. Например, MySetting=.

В рамках одной и той же команды не смешивайте пары "ключ-значение" аргумента командной строки, которые используют = с парами "ключ-значение" с пробелом.

Сопоставления переключений

Сопоставление параметров позволяет указать логику замены имен ключей. Предоставьте словарь замены параметров для метода AddCommandLine.

В словаре сопоставлений переключений выполняется поиск ключа, который совпадает с ключом, предоставляемым аргументом командной строки. Если ключ в командной строке находится в словаре, значение словаря передается обратно, чтобы установить пару "ключ-значение" в конфигурацию приложения. Сопоставление переключений необходимо для любого ключа командной строки с префиксом из одного дефиса (-).

Правила ключей из словаря сопоставления переключений:

  • Параметры должны начинаться с - или --.
  • Словарь сопоставлений переключений не должен содержать повторяющиеся ключи.

Чтобы использовать словарь сопоставлений параметров, передайте его в вызов AddCommandLine:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

Выполните следующую команду, чтобы проверить замену ключа:

dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

В следующем коде показаны ключевые значения для замененных ключей:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'\n" +
                $"Key2: '{Config["Key2"]}'\n" +
                $"Key3: '{Config["Key3"]}'\n" +
                $"Key4: '{Config["Key4"]}'\n" +
                $"Key5: '{Config["Key5"]}'\n" +
                $"Key6: '{Config["Key6"]}'");
    }
}

Для приложений, использующих сопоставления переключений, в вызове CreateDefaultBuilder аргументы передаваться не должны. Вызов команды AddCommandLine метода CreateDefaultBuilder не включает сопоставленные параметры, и нет возможности передать словарь сопоставления параметров в CreateDefaultBuilder. Чтобы решить эту проблему, нужно не передавать аргументы команде CreateDefaultBuilder, а позволить методу AddCommandLine метода ConfigurationBuilder обрабатывать как аргументы, так и словарь сопоставления параметров.

Настройка среды и аргументов командной строки с помощью Visual Studio

Аргументы среды и командной строки можно задать в Visual Studio в диалоговом окне профилей запуска:

  • В Обозревателе решений щелкните проект правой кнопкой мыши и выберите Свойства.
  • Откройте вкладку Отладка > Общие и выберите пункт Открыть пользовательский интерфейс профилей запуска отладки.

Иерархическая модель конфигурации

API конфигурации считывает иерархические данные конфигурации, выполняя преобразование в плоскую структуру иерархических данных с использованием разделителя в ключах конфигурации.

Пример скачивания содержит следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Предпочтительный способ чтения иерархических данных конфигурации — использование шаблона параметров. Дополнительные сведения см. в разделе Привязка иерархических данных конфигурации в этом документе.

Методы GetSection и GetChildren доступны для изолирования разделов и дочерних элементов раздела в данных конфигурации. Эти методы описаны далее в разделе GetSection, GetChildren и Exists.

Ключи и значения конфигурации

Ключи конфигурации:

  • Не учитывают регистр. Например ConnectionString и connectionstring обрабатываются как эквивалентные ключи.
  • Если ключ и значение заданы в нескольких поставщиках конфигурации, используется значение из последнего добавленного поставщика. Дополнительные сведения см. в разделе Конфигурация по умолчанию.
  • Иерархические ключи
    • При взаимодействии с API конфигурации разделитель-двоеточие (:) поддерживается на всех платформах.
    • В переменных среды разделитель-двоеточие может не работать на всех платформах. Двойной знак подчеркивания (__) поддерживается на всех платформах и автоматически преобразовывается в двоеточие — :.
    • В Azure Key Vault иерархические ключи используют -- в качестве разделителя. Поставщик конфигурации Azure Key Vault автоматически заменяет -- на : при загрузке секретов в конфигурацию приложения.
  • ConfigurationBinder поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Привязка массива описана в разделе Привязка массива к классу.

Значения конфигурации:

  • Представляют собой строки.
  • Значение NULL не может храниться в конфигурации или быть привязанным к объектам.

Поставщики конфигураций

В следующей таблице показаны поставщики конфигурации, доступные для приложений ASP.NET Core.

Provider Предоставляет конфигурацию из
Поставщик конфигурации Azure Key Vault Azure Key Vault
Поставщик конфигурации приложения Azure Настройка приложения Azure
Поставщик конфигурации командной строки Параметры командной строки
Поставщик пользовательской конфигурации Источник пользователя
Поставщик конфигурации переменных среды Переменные среды
Поставщик конфигурации файла Файлы INI, JSON и XML
Поставщик конфигурации ключа для каждого файла справочных файлов;
Поставщик конфигурации памяти Коллекции оперативной памяти
Секреты пользователя Файл в каталоге профиля пользователя

Источники конфигурации считываются в том порядке, в котором указываются их поставщики конфигурации. Порядок поставщиков конфигурации в коде соответствует приоритетам ваших основных источников конфигурации, требуемых приложением.

Типичная последовательность поставщиков конфигурации.

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Секреты пользователя
  4. Переменные среды, использующие поставщик конфигурации переменных среды.
  5. Аргументы командной строки, использующие поставщик конфигурации командной строки.

Общепринятой практикой является добавление поставщика конфигурации командной строки последним в ряду поставщиков, чтобы аргументы командной строки могли переопределять конфигурацию, установленную другими поставщиками.

Предыдущая последовательность поставщиков используется в конфигурации по умолчанию.

Префиксы строк подключения

API конфигурации имеет особые правила обработки для четырех переменных среды строки подключения. Эти строки подключения участвуют в настройке строк подключения Azure для среды приложения. Переменные среды с префиксами, указанными в таблице, загружаются в приложение с конфигурацией по умолчанию или если префикс не предоставлен для AddEnvironmentVariables.

Префикс строки подключения Provider
CUSTOMCONNSTR_ Поставщик пользователя
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ База данных SQL Azure
SQLCONNSTR_ SQL Server

Когда переменная среды обнаруживается и загружается в конфигурацию с одним из четырех префиксов, приведенных в таблице, происходит следующее.

  • Ключ конфигурации создается путем удаления префикса переменных среды и добавления ключа раздела конфигурации (ConnectionStrings).
  • Создается новая пара "ключ — значение" конфигурации, которая представляет поставщика подключения базы данных (за исключением CUSTOMCONNSTR_, который не имеет указанного поставщика).
Ключ переменной среды Преобразованный ключ конфигурации Запись конфигурации поставщика
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Запись конфигурации не создана.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient

Поставщик конфигурации файла

FileConfigurationProvider является базовым классом для загрузки конфигурации из файловой системы. Следующие поставщики конфигурации являются производными от FileConfigurationProvider:

Поставщик конфигурации INI

IniConfigurationProvider загружает конфигурацию из пары "ключ — значение" INI-файла во время выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyIniConfig.ini и MyIniConfig.{Environment}.ini переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Поставщик конфигурации JSON

Поставщик JsonConfigurationProvider загружает конфигурацию из пар "ключ-значение" файла JSON.

Перегрузки могут указывать:

  • Файл является обязательным или нет.
  • Будет ли перезагружена конфигурация, если файл изменится.

Рассмотрим следующий код:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Предыдущий код:

  • Настраивает JSпоставщик конфигурации ON для загрузки MyConfig.json файла со следующими параметрами:
    • optional: true: файл является необязательным.
    • reloadOnChange: true : файл перезагружается при сохранении изменений.
  • Считывает поставщики конфигурации по умолчанию перед файлом MyConfig.json . Параметры в MyConfig.json параметре переопределения файла в поставщиках конфигурации по умолчанию, включая поставщика конфигурации переменных среды и поставщика конфигурации командной строки.

Как правило, не рекомендуется использовать специальный файл JSON, переопределяющий значения, заданные в поставщике конфигурации переменных среды и поставщике конфигурации командной строки.

Поставщик конфигурации XML

XmlConfigurationProvider загружает конфигурацию из пары "ключ — значение" XML-файла в среде выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyXMLFile.xml и MyXMLFile.{Environment}.xml переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyXMLFile.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Повторяющиеся элементы, использующие то же имя элемента, работают, если атрибут name используется для различения элементов.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value 00</key>
    <key name="key1">value 01</key>
  </section>
  <section name="section1">
    <key name="key0">value 10</key>
    <key name="key1">value 11</key>
  </section>
</configuration>

Следующий код считывает предыдущий файл конфигурации и отображает ключи и значения:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

Атрибуты можно использовать для предоставления значений.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

Предыдущий файл конфигурации загружает следующие ключи с помощью value.

  • key:attribute
  • section:key:attribute

Поставщик конфигурации ключа для каждого файла

KeyPerFileConfigurationProvider использует файлы каталога как пары "ключ — значение" конфигурации. Ключ является именем файла. Значение содержит содержимое файла. Поставщик конфигурации ключа для каждого файла используется в сценариях размещения Docker.

Чтобы активировать конфигурацию ключа для каждого файла, вызовите метод расширения AddKeyPerFile в экземпляре ConfigurationBuilder. Значение параметра directoryPath должно быть абсолютным путем к файлам.

Перегрузки позволяют указать следующее.

  • Action<KeyPerFileConfigurationSource> — делегат, который настраивает источник.
  • Обязательно ли указывать каталог и путь к каталогу.

Двойное подчеркивание (__) используется в качестве разделителя ключа конфигурации в именах файлов. Например, в имени файла Logging__LogLevel__System создается ключ конфигурации Logging:LogLevel:System.

Чтобы указать конфигурацию приложения, при сборке веб-узла вызовите ConfigureAppConfiguration.

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Поставщик конфигурации памяти

MemoryConfigurationProvider использует коллекцию памяти в качестве пар "ключ — значение" конфигурации.

Следующий код добавляет коллекцию памяти в систему конфигурации:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В следующем коде из примера загрузки отображаются перечисленные выше параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

В предыдущем коде config.AddInMemoryCollection(Dict) добавляется после поставщиков конфигурации по умолчанию. Пример упорядочения поставщиков конфигурации см. в разделе Поставщик конфигурации JSON.

В разделе Привязка массива вы найдете еще один пример использования MemoryConfigurationProvider.

Конфигурация конечной точки Kestrel

Конфигурация конкретной конечной точки Kestrel переопределяет все межсерверные конфигурации конечной точки. Конфигурации межсерверных конечных точек включают:

Обратите внимание на следующий файл appsettings.json, используемый в веб-приложении ASP.NET Core:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Если предыдущая выделенная разметка используется в веб-приложении ASP.NET Core и приложение запускается в командной строке со следующей конфигурацией межсерверной конечной точки:

dotnet run --urls="https://localhost:7777"

Kestrel привязывается к конечной точке, настроенной специально для Kestrel в файле appsettings.json (https://localhost:9999), а не https://localhost:7777.

Рассмотрим конкретную конечную точку Kestrel, настроенную в качестве переменной среды:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

В предыдущей переменной среды Https является именем конкретной конечной точки Kestrel. Предыдущий файл appsettings.json также определяет Kestrel конкретную конечную точку с именем Https. По умолчанию переменные среды, использующие поставщик конфигурации переменных среды считываются после appsettings.{Environment}.json. Поэтому для конечной точки Https используется предыдущая переменная среды.

GetValue

ConfigurationBinder.GetValue извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

В приведенном выше коде, если NumberKey отсутствует в конфигурации, используется значение по умолчанию 99.

GetSection, GetChildren и Exists

В следующих примерах рассмотрим файл MySubsection.json.

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Следующий код добавляется MySubsection.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection возвращает подраздел конфигурации с указанным ключом подраздела.

Следующий код возвращает значения для section1:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Следующий код возвращает значения для section2:subsection0:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

Значение GetSection никогда не возвращает значение null. Если соответствующий раздел не найден, возвращается пустой параметр IConfigurationSection.

Когда GetSection возвращает соответствующий раздел, Value не заполняется. Key и Path возвращаются, если раздел существует.

GetChildren и Exists

Следующий код вызывает IConfiguration.GetChildren и возвращает значения для section2:subsection0:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Предыдущие вызовы ConfigurationExtensions.Exists кода для проверки наличия раздела:

Привязка массива

ConfigurationBinder.Bind поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Любой формат массива, который предоставляет сегмент числового ключа способен привязать массив к массиву класса POCO.

Рассмотрим MyArray.jsonпример скачивания:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Следующий код добавляется MyArray.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Следующий код считывает конфигурацию и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample? _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
       _array = Config.GetSection("array").Get<ArrayExample>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

В предыдущих выходных данных индекс 3 имеет значение value40, соответствующее "4": "value40", в файле MyArray.json. Индексы привязанного массива непрерывны и не привязаны к индексу ключа конфигурации. Модуль привязки конфигурации не поддерживает привязку значений NULL или создание записей NULL в связанных объектах.

Поставщик пользовательской конфигурации

Пример приложения демонстрирует, как создать базовый поставщик конфигурации, который считывает пары "ключ — значение" конфигурации из базы данных, используя Entity Framework (EF).

Поставщик имеет следующие характеристики.

  • База данных в памяти EF используется для демонстрационных целей. Чтобы использовать базу данных, для которой требуется строка подключения, выполните вторичный ConfigurationBuilder, чтобы предоставить строку подключения от другого поставщика конфигурации.
  • Поставщик считывает таблицу базы данных в конфигурации при запуске. Поставщик не запрашивает базу данных для каждого ключа.
  • Функция перезагрузки на изменение не реализована, поэтому обновление базы данных после запуска приложения не влияет на конфигурацию приложения.

Определите сущность EFConfigurationValue для хранения значений конфигурации в базе данных.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

Добавьте EFConfigurationContext в хранилище и обратитесь к настроенным значениям.

EFConfigurationProvider/EFConfigurationContext.cs:

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions<EFConfigurationContext> options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

Создайте класс, реализующий перехватчик IConfigurationSource.

EFConfigurationProvider/EFConfigurationSource.cs:

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) => _optionsAction = optionsAction;

    public IConfigurationProvider Build(IConfigurationBuilder builder) => new EFConfigurationProvider(_optionsAction);
}

Создайте пользовательский поставщик конфигурации путем наследования от ConfigurationProvider. Поставщик конфигурации инициализирует пустую базу данных. Так как конфигурационные ключи не учитывают регистр, словарь, используемый для инициализации базы данных, создается с помощью функции сравнения без учета регистра (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity-2005
        var configValues =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                    { "quote1", "I aim to misbehave." },
                    { "quote2", "I swallowed a bug." },
                    { "quote3", "You can't stop the signal, Mal." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue
            {
                Id = kvp.Key,
                Value = kvp.Value
            })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Метод расширения AddEFConfiguration позволяет добавить источник конфигурации к ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
               this IConfigurationBuilder builder,
               Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

В следующем коде показано, как использовать настраиваемый EFConfigurationProvider в Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

Конфигурация доступа с внедрением зависимостей (DI)

Конфигурацию можно внедрить в службы с помощью внедрения зависимостей (DI) путем разрешения службы IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Сведения о том, как получить доступ к значениям с помощью IConfiguration, см. в разделах GetValue и GetSection, GetChildren и Exists данной статьи.

Конфигурация доступа в RazorPages

В следующем коде отображаются данные конфигурации в RazorPage:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

В следующем коде MyOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

В следующей разметке для разрешения и вывода значений параметров используется директива @injectRazor.

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Доступ к конфигурации в файле представления MVC

В следующем коде отображаются данные конфигурации в представлении MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Доступ к конфигурации в Program.cs

Следующий код получает доступ к конфигурации в файле Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

В appsettings.json предыдущем примере:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Настройка параметров с помощью делегата

Параметры, настроенные в делегате, переопределяют значения, заданные в поставщиках конфигурации.

В приведенном ниже коде в контейнер службы добавляется служба IConfigureOptions<TOptions>. Она использует делегат для настройки значений для MyOptions:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

Следующий код отображает значения параметров:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

В предыдущем примере значения Option1 и Option2 задаются в файле appsettings.json, а затем переопределяются настроенным делегатом.

Конфигурация узла и приложения

Перед настройкой и запуском приложения настройте и запустите узел. Узел отвечает за запуск приложения и управление временем существования. Как приложение, так и узел настраиваются с использованием поставщиков конфигурации, описанных в этом разделе. Пары "ключ — значение" конфигурации узлов также включаются в конфигурацию приложения. Дополнительные сведения о том, как используются поставщики конфигурации при создании узла и как источники конфигурации влияют на его настройку, см. в статье Основы ASP.NET Core.

Конфигурация узла по умолчанию

Подробные сведения о конфигурации по умолчанию при использовании веб-узла см. в разделе о версии ASP.NET Core 2.2 в этой статье.

  • Конфигурация узла предоставляется из:
  • Конфигурация веб-узла по умолчанию устанавливается (ConfigureWebHostDefaults):
    • Kestrel используется в качестве веб-сервера и настраивается посредством поставщиков конфигурации приложения.
    • Добавьте ПО промежуточного слоя фильтрации узлов.
    • Если переменной среды ASPNETCORE_FORWARDEDHEADERS_ENABLED присвоено значение true, добавьте ПО промежуточного слоя перенаправления заголовков.
    • Включите интеграцию служб IIS.

Прочая конфигурация

Этот раздел относится только к конфигурации приложений. Другие аспекты запуска и размещения приложений ASP.NET Core настраиваются с помощью файлов конфигурации, которые не рассматриваются в этом разделе.

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде.

Дополнительные сведения о переносе конфигурации приложений из более ранних версий ASP.NET см. в разделе "Обновление от ASP.NET до ASP.NET Core".

Добавление конфигурации из внешней сборки

Реализация IHostingStartup позволяет при запуске добавлять в приложение улучшения из внешней сборки вне приложения класса Startup. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Генератор источника привязки конфигурации

Генератор источника привязки конфигурации предоставляет AOT и удобную конфигурацию. Дополнительные сведения см. в разделе генератор источника привязки конфигурации.

Дополнительные ресурсы

Настройка приложения в ASP.NET Core выполняется с помощью одного или нескольких поставщиков конфигурации. Поставщики конфигурации получают данные конфигурации в парах "ключ-значение" из различных источников:

  • файлов параметров, таких как appsettings.json;
  • Переменные среды
  • Azure Key Vault
  • Настройка приложения Azure
  • Аргументы командной строки
  • пользовательские поставщики, установленные или созданные;
  • справочных файлов;
  • объектов .NET в памяти;

В этой статье приведены сведения о конфигурации в ASP.NET Core. Сведения об использовании конфигурации в консольных приложениях см. в статье Конфигурация .NET.

Конфигурация приложения и узла

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Шаблоны ASP.NET Core создают объект WebApplicationBuilder, содержащий узел. Хотя определенные настройки доступны в поставщиках конфигурации и узла, и приложения, как правило, нужно использовать конфигурацию узла только для необходимых ему настроек.

Конфигурация приложения имеет наивысший приоритет и описана подробно в следующем разделе. Конфигурация узла вторична по отношению к конфигурации приложения, и она описана в этой статье.

Источники конфигурации приложения по умолчанию

Веб-приложения ASP.NET Core, созданные с помощью dotnet new или Visual Studio, создают следующий код:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder инициализирует новый экземпляр класса WebApplicationBuilder с предварительно настроенными значениями по умолчанию. Инициализированный экземпляр WebApplicationBuilder (builder) содержит конфигурацию по умолчанию для приложения с настройками в следующем порядке, от наиболее к наименее приоритетным:

  1. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  2. Переменные среды без префикса, использующие соответствующий поставщик конфигурации.
  3. секреты пользователя, когда приложение выполняется в среде Development;
  4. appsettings.{Environment}.json с использованием поставщика конфигурации JSON. Например, appsettings.Production.json и appsettings.Development.json.
  5. appsettings.json с использованием поставщика конфигурации JSON.
  6. Откат к конфигурации узла, описанной в следующем разделе.

Источники конфигурации узла по умолчанию

В следующем списке содержатся источники конфигурации узла по умолчанию от самого высокого до низкого приоритета для WebApplicationBuilder:

  1. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  2. Переменные среды с префиксом DOTNET_, использующие поставщик конфигурации переменных среды.
  3. Переменные среды с префиксом ASPNETCORE_, использующие поставщик конфигурации переменных среды.

Для универсального узла .NET и веб-узла по умолчанию источники конфигурации узла по умолчанию от самого высокого до низкого приоритета:

  1. Переменные среды с префиксом ASPNETCORE_, использующие поставщик конфигурации переменных среды.
  2. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  3. Переменные среды с префиксом DOTNET_, использующие поставщик конфигурации переменных среды.

Если значение задано в конфигурации и узла, и приложения, то используется конфигурация приложения.

Переменные узла

Следующие переменные фиксируются на ранних этапах при инициализации построителей узлов и не затрагиваются конфигурацией приложения:

Все остальные параметры узла считываются не из конфигурации узла, а из конфигурации приложения.

URLS — один из множества стандартных параметров узла, не относящийся к начальной загрузке. Как и все параметры узла, не приведенные в списке выше, URLS считывается на более позднем этапе из конфигурации приложения. Конфигурация узла используется как страховочный вариант для конфигурации приложения, поэтому можно задать URLS в первой, но это будет переопределено любым источником в конфигурации приложения, например appsettings.json.

Подробнее см. раздел Изменение корневого каталога содержимого, имени приложения и среды, а также Изменение корневой папки содержимого, имени приложения и среды через переменные среды или командную строку.

Остальные разделы этой статьи относятся к конфигурации приложения.

Поставщики конфигурации приложения

В следующем коде отображаются включенные поставщики конфигурации в том порядке, в котором они были добавлены:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "\n";
        }

        return Content(str);
    }
}

В приведенном выше списке источников конфигурации по умолчанию от наиболее к наименее приоритетным поставщики отображаются в порядке, обратному тому, в котором они добавляются в создаваемое из шаблона приложение. Например, поставщик конфигурации JSON добавляется перед поставщиком конфигурации командной строки.

Поставщики конфигурации, добавляемые позже, имеют больший приоритет и переопределяют предыдущие параметры ключей. Например, если MyKey задан в appsettings.json и в среде, используется значение среды. При использовании поставщиков конфигурации по умолчанию поставщик конфигурации командной строки переопределяет остальных поставщиков.

Дополнительные сведения о CreateBuilder см. в разделе Параметры сборщика по умолчанию.

appsettings.json

Рассмотрим следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

JsonConfigurationProvider по умолчанию загружает конфигурацию в следующем порядке:

  1. appsettings.json
  2. appsettings.{Environment}.json: например, файлы appsettings.Production.json и appsettings.Development.json. Версия среды файла загружается на IHostingEnvironment.EnvironmentNameоснове . Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Значения appsettings.{Environment}.json переопределяют ключи в файле appsettings.json. Например, по умолчанию:

  • В среде разработки конфигурация appsettings.Development.json переопределяет значения в файле appsettings.json.
  • В производственной среде конфигурация appsettings.Production.json переопределяет значения в файле appsettings.json. Например, при развертывании приложения в Azure.

Если необходимо гарантировать значение конфигурации, см. раздел о GetValue. Предыдущий пример поддерживает только считывание строк и не поддерживает значение по умолчанию.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Комментарии в appsettings.json

Примечания и appsettings.jsonappsettings.{Environment}.jsonфайлы поддерживаются с помощью комментариев в стиле JavaScript или C#.

Привязка иерархических данных конфигурации с помощью шаблона параметров

Предпочтительный способ чтения связанных значений конфигурации — использование шаблона параметров. Например, чтобы считать следующие значения конфигурации:

  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

Создайте следующий класс PositionOptions:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

Класс параметров:

  • Должен быть неабстрактным с открытым конструктором без параметров.
  • Все открытые свойства чтения и записи типа привязаны.
  • Поля не привязаны. В приведенном выше коде свойство Position не привязано. Поле Position используется так, что строку "Position" не требуется жестко кодировать в приложении при привязке класса к поставщику конфигурации.

Следующий код:

  • Вызывает ConfigurationBinder.Bind для привязки класса PositionOptions к разделу Position.
  • Отображает данные конфигурации Position.
public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

    public Test22Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

ConfigurationBinder.Get<T> привязывает и возвращает указанный тип. Метод ConfigurationBinder.Get<T> может быть более удобным, чем ConfigurationBinder.Bind. В приведенном ниже примере кода демонстрируются способы использования ConfigurationBinder.Get<T> с классом PositionOptions:

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions? positionOptions { get; private set; }

    public Test21Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

Альтернативный подход при использовании шаблона параметров — привязать раздел Position и добавить его в контейнер службы внедрения зависимостей. В следующем коде PositionOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

С помощью приведенного выше кода следующий код считывает параметры расположения:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} \n" +
                       $"Name: {_options.Name}");
    }
}

Приведенном выше кода изменения в файле конфигурации JSON, внесенные после запуска приложения, не считываются. Чтобы считать изменения после запуска приложения, используйте IOptionsSnapshot.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Сведения о добавлении дополнительных файлов конфигурации JSON см. в разделе Поставщик конфигурации JSON этого документа.

Объединение коллекций служб

Рассмотрим следующий код, который регистрирует службы и настраивает параметры:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

builder.Services.AddScoped<IMyDependency, MyDependency>();
builder.Services.AddScoped<IMyDependency2, MyDependency2>();

var app = builder.Build();

Связанные группы регистраций можно переместить в метод расширения для регистрации служб. Например, службы конфигурации добавляются в следующий класс:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

Остальные службы регистрируются в аналогичном классе. Следующий код использует новые методы расширения для регистрации служб:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

Примечание. Каждый services.Add{GROUP_NAME} метод расширения добавляет и потенциально настраивает службы. Например, AddControllersWithViews добавляет контроллеры MVC служб с необходимыми представлениями, а AddRazorPages — службы, требуемые для работы Razor Pages.

Безопасность и секреты пользователей

Рекомендации по данным конфигурации:

  • Никогда не храните пароли или другие конфиденциальные данные в коде поставщика конфигурации или в файлах конфигурации обычного текста. Хранить секреты во время разработки можно с помощью диспетчера секретов.
  • Не используйте секреты рабочей среды в средах разработки и тестирования.
  • Указывайте секреты вне проекта, чтобы их нельзя было случайно зафиксировать в репозитории с исходным кодом.

По умолчанию источник конфигурации пользовательских секретов регистрируется после источников конфигурации JSON. Таким образом, ключи секретов пользователя имеют приоритет над ключами в appsettings.json и appsettings.{Environment}.json.

Дополнительные сведения о хранении паролей или других конфиденциальных данных:

В Azure Key Vault безопасно хранятся секреты приложений ASP.NET Core. Дополнительные сведения см. в статье Поставщик конфигурации Azure Key Vault в ASP.NET Core.

Переменные среды без префикса

К переменным среды без префикса относятся те, что не имеют префикса ASPNETCORE_ или DOTNET_. Для примера можно привести набор шаблонов веб-приложения ASP.NET Core "ASPNETCORE_ENVIRONMENT": "Development" в launchSettings.json. Дополнительные сведения о переменных среды ASPNETCORE_ и DOTNET_:

При использовании конфигурации по умолчаниюEnvironmentVariablesConfigurationProvider загружает конфигурацию из пар "ключ — значение" в переменных среды после чтения appsettings.json, appsettings.{Environment}.json и секретов пользователя. Поэтому значения ключей, считанные из среды, переопределяют значения, считанные из appsettings.json, appsettings.{Environment}.json и секретов пользователя.

Разделитель : не работает с иерархическими ключами переменных среды на всех платформах. __ (двойной символ подчеркивания):

  • Поддерживается всеми платформами. Например, разделитель : не поддерживается Bash, а __ — поддерживается.
  • Автоматически заменяется на :

Следующие команды set:

set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Предыдущие параметры среды:

  • Задаются только в процессах, запускаемых из командного окна, в котором они были установлены.
  • Не будут считываться браузерами, запущенными в Visual Studio.

Следующие команды setx можно использовать для задания ключей и значений среды в Windows. В отличие от set, параметры setx сохраняются. /M задает переменную в системной среде. Если параметр /M не используется, задается переменная среды пользователя.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Чтобы проверить, что предыдущие команды переопределяют appsettings.json и appsettings.{Environment}.json:

  • С помощью Visual Studio: выход и перезапуск Visual Studio.
  • С помощью интерфейса командной строки: запустите новое командное окно и введите dotnet run.

Вызовите AddEnvironmentVariables со строкой, чтобы указать префикс для переменных среды:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

В предыдущем коде:

Префикс отделяется при создании пары конфигурации "ключ-значение".

Следующие команды проверяют пользовательский префикс:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

Конфигурация по умолчанию загружает переменные среды и аргументы командной строки с префиксом DOTNET_ и ASPNETCORE_. Префиксы DOTNET_ и ASPNETCORE_ используются ASP.NET Core для конфигурации узла и приложения, но не для конфигурации пользователя. Дополнительные сведения о конфигурации узла и приложения см. в разделе Универсальный узел .NET.

В Службе приложений Azure выберите Новый параметр приложения на странице Параметры > Конфигурация. Параметры приложения Службы приложений Azure:

  • Шифруются, когда они неактивны, и передаются по зашифрованному каналу.
  • Предоставляются как переменные среды.

Дополнительные сведения см. в разделе Приложения Azure. Переопределение конфигурации приложения с помощью портала Azure.

Сведения о строках подключения к базе данных Azure см. в разделе Префиксы строк подключения.

Именование переменных среды

Имена переменных среды отражают структуру файла appsettings.json. Каждый элемент в иерархии отделяется двойным символом подчеркивания (предпочтительно) или двоеточием. Если структура элемента включает массив, индекс массива должен рассматриваться как дополнительное имя элемента в этом пути. Рассмотрим следующий файл appsettings.json и его эквивалентные значения, представленные в виде переменных среды:

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

Переменные среды

setx SmtpServer smtp.example.com
setx Logging__0__Name ToEmail
setx Logging__0__Level Critical
setx Logging__0__Args__FromAddress MySystem@example.com
setx Logging__0__Args__ToAddress SRE@example.com
setx Logging__1__Name ToConsole
setx Logging__1__Level Information

Переменные среды, заданные в созданном файле launchSettings.json

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде. Например, веб-шаблоны ASP.NET Core создают launchSettings.json файл, который задает конфигурацию конечной точки следующим образом:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

При настройке applicationUrl устанавливается переменная среды ASPNETCORE_URLS и переопределяются значения, заданные в среде.

Экранирование переменных среды в Linux

В Linux значения переменных среды URL-адресов нужно экранировать, чтобы их можно было проанализировать с помощью systemd. Используйте средство Linux systemd-escape, которое приостанавливает http:--localhost:5001.

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

Отображение переменных среды

Следующий код позволяет отобразить переменные среды и значения при запуске приложения, что может быть полезно при отладке параметров среды:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

Командная строка

При использовании конфигурации по умолчаниюCommandLineConfigurationProvider загружает конфигурацию из пар "ключ-значение" аргументов командной строки после следующих источников конфигурации:

По умолчанию значения конфигурации, заданные для значений конфигурации переопределения в командной строке, задаются для всех остальных поставщиков конфигурации.

Аргументы командной строки

Следующая команда задает ключи и значения с помощью =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью /:

dotnet run /MyKey "Using /" /Position:Title=Cmd /Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью --:

dotnet run --MyKey "Using --" --Position:Title=Cmd --Position:Name=Cmd_Rick

Значение ключа:

  • Должно соответствовать =, или ключ должен иметь префикс -- или /, когда значение следует за пробелом.
  • Является обязательным, если используется параметр =. Например, MySetting=.

В рамках одной и той же команды не смешивайте пары "ключ-значение" аргумента командной строки, которые используют = с парами "ключ-значение" с пробелом.

Сопоставления переключений

Сопоставление параметров позволяет указать логику замены имен ключей. Предоставьте словарь замены параметров для метода AddCommandLine.

В словаре сопоставлений переключений выполняется поиск ключа, который совпадает с ключом, предоставляемым аргументом командной строки. Если ключ в командной строке находится в словаре, значение словаря передается обратно, чтобы установить пару "ключ-значение" в конфигурацию приложения. Сопоставление переключений необходимо для любого ключа командной строки с префиксом из одного дефиса (-).

Правила ключей из словаря сопоставления переключений:

  • Параметры должны начинаться с - или --.
  • Словарь сопоставлений переключений не должен содержать повторяющиеся ключи.

Чтобы использовать словарь сопоставлений параметров, передайте его в вызов AddCommandLine:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

Выполните следующую команду, чтобы проверить замену ключа:

dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

В следующем коде показаны ключевые значения для замененных ключей:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'\n" +
                $"Key2: '{Config["Key2"]}'\n" +
                $"Key3: '{Config["Key3"]}'\n" +
                $"Key4: '{Config["Key4"]}'\n" +
                $"Key5: '{Config["Key5"]}'\n" +
                $"Key6: '{Config["Key6"]}'");
    }
}

Для приложений, использующих сопоставления переключений, в вызове CreateDefaultBuilder аргументы передаваться не должны. Вызов команды AddCommandLine метода CreateDefaultBuilder не включает сопоставленные параметры, и нет возможности передать словарь сопоставления параметров в CreateDefaultBuilder. Чтобы решить эту проблему, нужно не передавать аргументы команде CreateDefaultBuilder, а позволить методу AddCommandLine метода ConfigurationBuilder обрабатывать как аргументы, так и словарь сопоставления параметров.

Настройка среды и аргументов командной строки с помощью Visual Studio

Аргументы среды и командной строки можно задать в Visual Studio в диалоговом окне профилей запуска:

  • В Обозревателе решений щелкните проект правой кнопкой мыши и выберите Свойства.
  • Откройте вкладку Отладка > Общие и выберите пункт Открыть пользовательский интерфейс профилей запуска отладки.

Иерархическая модель конфигурации

API конфигурации считывает иерархические данные конфигурации, выполняя преобразование в плоскую структуру иерархических данных с использованием разделителя в ключах конфигурации.

Пример скачивания содержит следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Предпочтительный способ чтения иерархических данных конфигурации — использование шаблона параметров. Дополнительные сведения см. в разделе Привязка иерархических данных конфигурации в этом документе.

Методы GetSection и GetChildren доступны для изолирования разделов и дочерних элементов раздела в данных конфигурации. Эти методы описаны далее в разделе GetSection, GetChildren и Exists.

Ключи и значения конфигурации

Ключи конфигурации:

  • Не учитывают регистр. Например ConnectionString и connectionstring обрабатываются как эквивалентные ключи.
  • Если ключ и значение заданы в нескольких поставщиках конфигурации, используется значение из последнего добавленного поставщика. Дополнительные сведения см. в разделе Конфигурация по умолчанию.
  • Иерархические ключи
    • При взаимодействии с API конфигурации разделитель-двоеточие (:) поддерживается на всех платформах.
    • В переменных среды разделитель-двоеточие может не работать на всех платформах. Двойной знак подчеркивания (__) поддерживается на всех платформах и автоматически преобразовывается в двоеточие — :.
    • В Azure Key Vault иерархические ключи используют -- в качестве разделителя. Поставщик конфигурации Azure Key Vault автоматически заменяет -- на : при загрузке секретов в конфигурацию приложения.
  • ConfigurationBinder поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Привязка массива описана в разделе Привязка массива к классу.

Значения конфигурации:

  • Представляют собой строки.
  • Значение NULL не может храниться в конфигурации или быть привязанным к объектам.

Поставщики конфигураций

В следующей таблице показаны поставщики конфигурации, доступные для приложений ASP.NET Core.

Provider Предоставляет конфигурацию из
Поставщик конфигурации Azure Key Vault Azure Key Vault
Поставщик конфигурации приложения Azure Настройка приложения Azure
Поставщик конфигурации командной строки Параметры командной строки
Поставщик пользовательской конфигурации Источник пользователя
Поставщик конфигурации переменных среды Переменные среды
Поставщик конфигурации файла Файлы INI, JSON и XML
Поставщик конфигурации ключа для каждого файла справочных файлов;
Поставщик конфигурации памяти Коллекции оперативной памяти
Секреты пользователя Файл в каталоге профиля пользователя

Источники конфигурации считываются в том порядке, в котором указываются их поставщики конфигурации. Порядок поставщиков конфигурации в коде соответствует приоритетам ваших основных источников конфигурации, требуемых приложением.

Типичная последовательность поставщиков конфигурации.

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Секреты пользователя
  4. Переменные среды, использующие поставщик конфигурации переменных среды.
  5. Аргументы командной строки, использующие поставщик конфигурации командной строки.

Общепринятой практикой является добавление поставщика конфигурации командной строки последним в ряду поставщиков, чтобы аргументы командной строки могли переопределять конфигурацию, установленную другими поставщиками.

Предыдущая последовательность поставщиков используется в конфигурации по умолчанию.

Префиксы строк подключения

API конфигурации имеет особые правила обработки для четырех переменных среды строки подключения. Эти строки подключения участвуют в настройке строк подключения Azure для среды приложения. Переменные среды с префиксами, указанными в таблице, загружаются в приложение с конфигурацией по умолчанию или если префикс не предоставлен для AddEnvironmentVariables.

Префикс строки подключения Provider
CUSTOMCONNSTR_ Поставщик пользователя
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ База данных SQL Azure
SQLCONNSTR_ SQL Server

Когда переменная среды обнаруживается и загружается в конфигурацию с одним из четырех префиксов, приведенных в таблице, происходит следующее.

  • Ключ конфигурации создается путем удаления префикса переменных среды и добавления ключа раздела конфигурации (ConnectionStrings).
  • Создается новая пара "ключ — значение" конфигурации, которая представляет поставщика подключения базы данных (за исключением CUSTOMCONNSTR_, который не имеет указанного поставщика).
Ключ переменной среды Преобразованный ключ конфигурации Запись конфигурации поставщика
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Запись конфигурации не создана.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient

Поставщик конфигурации файла

FileConfigurationProvider является базовым классом для загрузки конфигурации из файловой системы. Следующие поставщики конфигурации являются производными от FileConfigurationProvider:

Поставщик конфигурации INI

IniConfigurationProvider загружает конфигурацию из пары "ключ — значение" INI-файла во время выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyIniConfig.ini и MyIniConfig.{Environment}.ini переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Поставщик конфигурации JSON

Поставщик JsonConfigurationProvider загружает конфигурацию из пар "ключ-значение" файла JSON.

Перегрузки могут указывать:

  • Файл является обязательным или нет.
  • Будет ли перезагружена конфигурация, если файл изменится.

Рассмотрим следующий код:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Предыдущий код:

  • Настраивает JSпоставщик конфигурации ON для загрузки MyConfig.json файла со следующими параметрами:
    • optional: true: файл является необязательным.
    • reloadOnChange: true : файл перезагружается при сохранении изменений.
  • Считывает поставщики конфигурации по умолчанию перед файлом MyConfig.json . Параметры в MyConfig.json параметре переопределения файла в поставщиках конфигурации по умолчанию, включая поставщика конфигурации переменных среды и поставщика конфигурации командной строки.

Как правило, не рекомендуется использовать специальный файл JSON, переопределяющий значения, заданные в поставщике конфигурации переменных среды и поставщике конфигурации командной строки.

Поставщик конфигурации XML

XmlConfigurationProvider загружает конфигурацию из пары "ключ — значение" XML-файла в среде выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyXMLFile.xml и MyXMLFile.{Environment}.xml переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyXMLFile.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Повторяющиеся элементы, использующие то же имя элемента, работают, если атрибут name используется для различения элементов.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value 00</key>
    <key name="key1">value 01</key>
  </section>
  <section name="section1">
    <key name="key0">value 10</key>
    <key name="key1">value 11</key>
  </section>
</configuration>

Следующий код считывает предыдущий файл конфигурации и отображает ключи и значения:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

Атрибуты можно использовать для предоставления значений.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

Предыдущий файл конфигурации загружает следующие ключи с помощью value.

  • key:attribute
  • section:key:attribute

Поставщик конфигурации ключа для каждого файла

KeyPerFileConfigurationProvider использует файлы каталога как пары "ключ — значение" конфигурации. Ключ является именем файла. Значение содержит содержимое файла. Поставщик конфигурации ключа для каждого файла используется в сценариях размещения Docker.

Чтобы активировать конфигурацию ключа для каждого файла, вызовите метод расширения AddKeyPerFile в экземпляре ConfigurationBuilder. Значение параметра directoryPath должно быть абсолютным путем к файлам.

Перегрузки позволяют указать следующее.

  • Action<KeyPerFileConfigurationSource> — делегат, который настраивает источник.
  • Обязательно ли указывать каталог и путь к каталогу.

Двойное подчеркивание (__) используется в качестве разделителя ключа конфигурации в именах файлов. Например, в имени файла Logging__LogLevel__System создается ключ конфигурации Logging:LogLevel:System.

Чтобы указать конфигурацию приложения, при сборке веб-узла вызовите ConfigureAppConfiguration.

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Поставщик конфигурации памяти

MemoryConfigurationProvider использует коллекцию памяти в качестве пар "ключ — значение" конфигурации.

Следующий код добавляет коллекцию памяти в систему конфигурации:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В следующем коде из примера загрузки отображаются перечисленные выше параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

В предыдущем коде config.AddInMemoryCollection(Dict) добавляется после поставщиков конфигурации по умолчанию. Пример упорядочения поставщиков конфигурации см. в разделе Поставщик конфигурации JSON.

В разделе Привязка массива вы найдете еще один пример использования MemoryConfigurationProvider.

Конфигурация конечной точки Kestrel

Конфигурация конкретной конечной точки Kestrel переопределяет все межсерверные конфигурации конечной точки. Конфигурации межсерверных конечных точек включают:

Обратите внимание на следующий файл appsettings.json, используемый в веб-приложении ASP.NET Core:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Если предыдущая выделенная разметка используется в веб-приложении ASP.NET Core и приложение запускается в командной строке со следующей конфигурацией межсерверной конечной точки:

dotnet run --urls="https://localhost:7777"

Kestrel привязывается к конечной точке, настроенной специально для Kestrel в файле appsettings.json (https://localhost:9999), а не https://localhost:7777.

Рассмотрим конкретную конечную точку Kestrel, настроенную в качестве переменной среды:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

В предыдущей переменной среды Https является именем конкретной конечной точки Kestrel. Предыдущий файл appsettings.json также определяет Kestrel конкретную конечную точку с именем Https. По умолчанию переменные среды, использующие поставщик конфигурации переменных среды считываются после appsettings.{Environment}.json. Поэтому для конечной точки Https используется предыдущая переменная среды.

GetValue

ConfigurationBinder.GetValue извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

В приведенном выше коде, если NumberKey отсутствует в конфигурации, используется значение по умолчанию 99.

GetSection, GetChildren и Exists

В следующих примерах рассмотрим файл MySubsection.json.

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Следующий код добавляется MySubsection.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection возвращает подраздел конфигурации с указанным ключом подраздела.

Следующий код возвращает значения для section1:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Следующий код возвращает значения для section2:subsection0:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

Значение GetSection никогда не возвращает значение null. Если соответствующий раздел не найден, возвращается пустой параметр IConfigurationSection.

Когда GetSection возвращает соответствующий раздел, Value не заполняется. Key и Path возвращаются, если раздел существует.

GetChildren и Exists

Следующий код вызывает IConfiguration.GetChildren и возвращает значения для section2:subsection0:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Предыдущие вызовы ConfigurationExtensions.Exists кода для проверки наличия раздела:

Привязка массива

ConfigurationBinder.Bind поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Любой формат массива, который предоставляет сегмент числового ключа способен привязать массив к массиву класса POCO.

Рассмотрим MyArray.jsonпример скачивания:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Следующий код добавляется MyArray.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Следующий код считывает конфигурацию и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample? _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
       _array = Config.GetSection("array").Get<ArrayExample>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

В предыдущих выходных данных индекс 3 имеет значение value40, соответствующее "4": "value40", в файле MyArray.json. Индексы привязанного массива непрерывны и не привязаны к индексу ключа конфигурации. Модуль привязки конфигурации не поддерживает привязку значений NULL или создание записей NULL в связанных объектах.

Поставщик пользовательской конфигурации

Пример приложения демонстрирует, как создать базовый поставщик конфигурации, который считывает пары "ключ — значение" конфигурации из базы данных, используя Entity Framework (EF).

Поставщик имеет следующие характеристики.

  • База данных в памяти EF используется для демонстрационных целей. Чтобы использовать базу данных, для которой требуется строка подключения, выполните вторичный ConfigurationBuilder, чтобы предоставить строку подключения от другого поставщика конфигурации.
  • Поставщик считывает таблицу базы данных в конфигурации при запуске. Поставщик не запрашивает базу данных для каждого ключа.
  • Функция перезагрузки на изменение не реализована, поэтому обновление базы данных после запуска приложения не влияет на конфигурацию приложения.

Определите сущность EFConfigurationValue для хранения значений конфигурации в базе данных.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

Добавьте EFConfigurationContext в хранилище и обратитесь к настроенным значениям.

EFConfigurationProvider/EFConfigurationContext.cs:

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions<EFConfigurationContext> options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

Создайте класс, реализующий перехватчик IConfigurationSource.

EFConfigurationProvider/EFConfigurationSource.cs:

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) => _optionsAction = optionsAction;

    public IConfigurationProvider Build(IConfigurationBuilder builder) => new EFConfigurationProvider(_optionsAction);
}

Создайте пользовательский поставщик конфигурации путем наследования от ConfigurationProvider. Поставщик конфигурации инициализирует пустую базу данных. Так как конфигурационные ключи не учитывают регистр, словарь, используемый для инициализации базы данных, создается с помощью функции сравнения без учета регистра (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity-2005
        var configValues =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                    { "quote1", "I aim to misbehave." },
                    { "quote2", "I swallowed a bug." },
                    { "quote3", "You can't stop the signal, Mal." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue
            {
                Id = kvp.Key,
                Value = kvp.Value
            })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Метод расширения AddEFConfiguration позволяет добавить источник конфигурации к ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
               this IConfigurationBuilder builder,
               Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

В следующем коде показано, как использовать настраиваемый EFConfigurationProvider в Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

Конфигурация доступа с внедрением зависимостей (DI)

Конфигурацию можно внедрить в службы с помощью внедрения зависимостей (DI) путем разрешения службы IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Сведения о том, как получить доступ к значениям с помощью IConfiguration, см. в разделах GetValue и GetSection, GetChildren и Exists данной статьи.

Конфигурация доступа в RazorPages

В следующем коде отображаются данные конфигурации в RazorPage:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

В следующем коде MyOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

В следующей разметке для разрешения и вывода значений параметров используется директива @injectRazor.

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Доступ к конфигурации в файле представления MVC

В следующем коде отображаются данные конфигурации в представлении MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Доступ к конфигурации в Program.cs

Следующий код получает доступ к конфигурации в файле Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

В appsettings.json предыдущем примере:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Настройка параметров с помощью делегата

Параметры, настроенные в делегате, переопределяют значения, заданные в поставщиках конфигурации.

В приведенном ниже коде в контейнер службы добавляется служба IConfigureOptions<TOptions>. Она использует делегат для настройки значений для MyOptions:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

Следующий код отображает значения параметров:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

В предыдущем примере значения Option1 и Option2 задаются в файле appsettings.json, а затем переопределяются настроенным делегатом.

Конфигурация узла и приложения

Перед настройкой и запуском приложения настройте и запустите узел. Узел отвечает за запуск приложения и управление временем существования. Как приложение, так и узел настраиваются с использованием поставщиков конфигурации, описанных в этом разделе. Пары "ключ — значение" конфигурации узлов также включаются в конфигурацию приложения. Дополнительные сведения о том, как используются поставщики конфигурации при создании узла и как источники конфигурации влияют на его настройку, см. в статье Основы ASP.NET Core.

Конфигурация узла по умолчанию

Подробные сведения о конфигурации по умолчанию при использовании веб-узла см. в разделе о версии ASP.NET Core 2.2 в этой статье.

  • Конфигурация узла предоставляется из:
  • Конфигурация веб-узла по умолчанию устанавливается (ConfigureWebHostDefaults):
    • Kestrel используется в качестве веб-сервера и настраивается посредством поставщиков конфигурации приложения.
    • Добавьте ПО промежуточного слоя фильтрации узлов.
    • Если переменной среды ASPNETCORE_FORWARDEDHEADERS_ENABLED присвоено значение true, добавьте ПО промежуточного слоя перенаправления заголовков.
    • Включите интеграцию служб IIS.

Прочая конфигурация

Этот раздел относится только к конфигурации приложений. Другие аспекты запуска и размещения приложений ASP.NET Core настраиваются с помощью файлов конфигурации, которые не рассматриваются в этом разделе.

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде.

Дополнительные сведения о переносе конфигурации приложений из более ранних версий ASP.NET см. в разделе "Обновление от ASP.NET до ASP.NET Core".

Добавление конфигурации из внешней сборки

Реализация IHostingStartup позволяет при запуске добавлять в приложение улучшения из внешней сборки вне приложения класса Startup. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Дополнительные ресурсы

Настройка приложения в ASP.NET Core выполняется с помощью одного или нескольких поставщиков конфигурации. Поставщики конфигурации получают данные конфигурации в парах "ключ-значение" из различных источников:

  • файлов параметров, таких как appsettings.json;
  • Переменные среды
  • Azure Key Vault
  • Настройка приложения Azure
  • Аргументы командной строки
  • пользовательские поставщики, установленные или созданные;
  • справочных файлов;
  • объектов .NET в памяти;

В этой статье приведены сведения о конфигурации в ASP.NET Core. Сведения об использовании конфигурации в консольных приложениях см. в статье Конфигурация .NET.

Конфигурация приложения и узла

Приложения ASP.NET Core настраивают и запускают узел. Узел отвечает за запуск приложения и управление временем существования. Шаблоны ASP.NET Core создают объект WebApplicationBuilder, содержащий узел. Хотя определенные настройки доступны в поставщиках конфигурации и узла, и приложения, как правило, нужно использовать конфигурацию узла только для необходимых ему настроек.

Конфигурация приложения имеет наивысший приоритет и описана подробно в следующем разделе. Конфигурация узла вторична по отношению к конфигурации приложения, и она описана в этой статье.

Источники конфигурации приложения по умолчанию

Веб-приложения ASP.NET Core, созданные с помощью dotnet new или Visual Studio, создают следующий код:

var builder = WebApplication.CreateBuilder(args);

WebApplication.CreateBuilder инициализирует новый экземпляр класса WebApplicationBuilder с предварительно настроенными значениями по умолчанию. Инициализированный экземпляр WebApplicationBuilder (builder) содержит конфигурацию по умолчанию для приложения с настройками в следующем порядке, от наиболее к наименее приоритетным:

  1. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  2. Переменные среды без префикса, использующие соответствующий поставщик конфигурации.
  3. секреты пользователя, когда приложение выполняется в среде Development;
  4. appsettings.{Environment}.json с использованием поставщика конфигурации JSON. Например, appsettings.Production.json и appsettings.Development.json.
  5. appsettings.json с использованием поставщика конфигурации JSON.
  6. Откат к конфигурации узла, описанной в следующем разделе.

Источники конфигурации узла по умолчанию

Следующий список содержит источники конфигурации узла по умолчанию от наиболее к наименее приоритетным:

  1. Переменные среды с префиксом ASPNETCORE_, использующие поставщик конфигурации переменных среды.
  2. Аргументы командной строки, использующие поставщик конфигурации командной строки.
  3. Переменные среды с префиксом DOTNET_, использующие поставщик конфигурации переменных среды.

Если значение задано в конфигурации и узла, и приложения, то используется конфигурация приложения.

См. пояснение в этом комментарии GitHub о том, почему в конфигурации узла переменные среды с префиксом ASPNETCORE_ имеют больший приоритет, чем аргументы командной строки.

Переменные узла

Следующие переменные фиксируются на ранних этапах при инициализации построителей узлов и не затрагиваются конфигурацией приложения:

Все остальные параметры узла считываются не из конфигурации узла, а из конфигурации приложения.

URLS — один из множества стандартных параметров узла, не относящийся к начальной загрузке. Как и все параметры узла, не приведенные в списке выше, URLS считывается на более позднем этапе из конфигурации приложения. Конфигурация узла используется как страховочный вариант для конфигурации приложения, поэтому можно задать URLS в первой, но это будет переопределено любым источником в конфигурации приложения, например appsettings.json.

Подробнее см. раздел Изменение корневого каталога содержимого, имени приложения и среды, а также Изменение корневой папки содержимого, имени приложения и среды через переменные среды или командную строку.

Остальные разделы этой статьи относятся к конфигурации приложения.

Поставщики конфигурации приложения

В следующем коде отображаются включенные поставщики конфигурации в том порядке, в котором они были добавлены:

public class Index2Model : PageModel
{
    private IConfigurationRoot ConfigRoot;

    public Index2Model(IConfiguration configRoot)
    {
        ConfigRoot = (IConfigurationRoot)configRoot;
    }

    public ContentResult OnGet()
    {           
        string str = "";
        foreach (var provider in ConfigRoot.Providers.ToList())
        {
            str += provider.ToString() + "\n";
        }

        return Content(str);
    }
}

В приведенном выше списке источников конфигурации по умолчанию от наиболее к наименее приоритетным поставщики отображаются в порядке, обратному тому, в котором они добавляются в создаваемое из шаблона приложение. Например, поставщик конфигурации JSON добавляется перед поставщиком конфигурации командной строки.

Поставщики конфигурации, добавляемые позже, имеют больший приоритет и переопределяют предыдущие параметры ключей. Например, если MyKey задан в appsettings.json и в среде, используется значение среды. При использовании поставщиков конфигурации по умолчанию поставщик конфигурации командной строки переопределяет остальных поставщиков.

Дополнительные сведения о CreateBuilder см. в разделе Параметры сборщика по умолчанию.

appsettings.json

Рассмотрим следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

JsonConfigurationProvider по умолчанию загружает конфигурацию в следующем порядке:

  1. appsettings.json
  2. appsettings.{Environment}.json: например, файлы appsettings.Production.json и appsettings.Development.json. Версия среды файла загружается на IHostingEnvironment.EnvironmentNameоснове . Дополнительные сведения см. в статье Использование нескольких сред в ASP.NET Core.

Значения appsettings.{Environment}.json переопределяют ключи в файле appsettings.json. Например, по умолчанию:

  • В среде разработки конфигурация appsettings.Development.json переопределяет значения в файле appsettings.json.
  • В производственной среде конфигурация appsettings.Production.json переопределяет значения в файле appsettings.json. Например, при развертывании приложения в Azure.

Если необходимо гарантировать значение конфигурации, см. раздел о GetValue. Предыдущий пример поддерживает только считывание строк и не поддерживает значение по умолчанию.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Привязка иерархических данных конфигурации с помощью шаблона параметров

Предпочтительный способ чтения связанных значений конфигурации — использование шаблона параметров. Например, чтобы считать следующие значения конфигурации:

  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  }

Создайте следующий класс PositionOptions:

public class PositionOptions
{
    public const string Position = "Position";

    public string Title { get; set; } = String.Empty;
    public string Name { get; set; } = String.Empty;
}

Класс параметров:

  • Должен быть неабстрактным с открытым конструктором без параметров.
  • Все открытые свойства чтения и записи типа привязаны.
  • Поля не привязаны. В приведенном выше коде свойство Position не привязано. Поле Position используется так, что строку "Position" не требуется жестко кодировать в приложении при привязке класса к поставщику конфигурации.

Следующий код:

  • Вызывает ConfigurationBinder.Bind для привязки класса PositionOptions к разделу Position.
  • Отображает данные конфигурации Position.
public class Test22Model : PageModel
{
    private readonly IConfiguration Configuration;

    public Test22Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var positionOptions = new PositionOptions();
        Configuration.GetSection(PositionOptions.Position).Bind(positionOptions);

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

ConfigurationBinder.Get<T> привязывает и возвращает указанный тип. Метод ConfigurationBinder.Get<T> может быть более удобным, чем ConfigurationBinder.Bind. В приведенном ниже примере кода демонстрируются способы использования ConfigurationBinder.Get<T> с классом PositionOptions:

public class Test21Model : PageModel
{
    private readonly IConfiguration Configuration;
    public PositionOptions? positionOptions { get; private set; }

    public Test21Model(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {            
        positionOptions = Configuration.GetSection(PositionOptions.Position)
                                                     .Get<PositionOptions>();

        return Content($"Title: {positionOptions.Title} \n" +
                       $"Name: {positionOptions.Name}");
    }
}

В приведенном выше коде по умолчанию считываются изменения в файле конфигурации JSON, внесенные после запуска приложения.

Альтернативный подход при использовании шаблона параметров — привязать раздел Position и добавить его в контейнер службы внедрения зависимостей. В следующем коде PositionOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));

var app = builder.Build();

С помощью приведенного выше кода следующий код считывает параметры расположения:

public class Test2Model : PageModel
{
    private readonly PositionOptions _options;

    public Test2Model(IOptions<PositionOptions> options)
    {
        _options = options.Value;
    }

    public ContentResult OnGet()
    {
        return Content($"Title: {_options.Title} \n" +
                       $"Name: {_options.Name}");
    }
}

Приведенном выше кода изменения в файле конфигурации JSON, внесенные после запуска приложения, не считываются. Чтобы считать изменения после запуска приложения, используйте IOptionsSnapshot.

С помощью конфигурации по умолчанию файлы appsettings.json и appsettings.{Environment}.json включаются с помощью reloadOnChange: true. Изменения, вносимые в файлы appsettings.json и appsettings.{Environment}.jsonпосле запуска приложения, считываются поставщиком конфигурации JSON.

Сведения о добавлении дополнительных файлов конфигурации JSON см. в разделе Поставщик конфигурации JSON этого документа.

Объединение коллекций служб

Рассмотрим следующий код, который регистрирует службы и настраивает параметры:

using ConfigSample.Options;
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<PositionOptions>(
    builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
    builder.Configuration.GetSection(ColorOptions.Color));

builder.Services.AddScoped<IMyDependency, MyDependency>();
builder.Services.AddScoped<IMyDependency2, MyDependency2>();

var app = builder.Build();

Связанные группы регистраций можно переместить в метод расширения для регистрации служб. Например, службы конфигурации добавляются в следующий класс:

using ConfigSample.Options;
using Microsoft.Extensions.Configuration;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();

            return services;
        }
    }
}

Остальные службы регистрируются в аналогичном классе. Следующий код использует новые методы расширения для регистрации служб:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

builder.Services.AddRazorPages();

var app = builder.Build();

Примечание. Каждый services.Add{GROUP_NAME} метод расширения добавляет и потенциально настраивает службы. Например, AddControllersWithViews добавляет контроллеры MVC служб с необходимыми представлениями, а AddRazorPages — службы, требуемые для работы Razor Pages.

Безопасность и секреты пользователей

Рекомендации по данным конфигурации:

  • Никогда не храните пароли или другие конфиденциальные данные в коде поставщика конфигурации или в файлах конфигурации обычного текста. Хранить секреты во время разработки можно с помощью диспетчера секретов.
  • Не используйте секреты рабочей среды в средах разработки и тестирования.
  • Указывайте секреты вне проекта, чтобы их нельзя было случайно зафиксировать в репозитории с исходным кодом.

По умолчанию источник конфигурации пользовательских секретов регистрируется после источников конфигурации JSON. Таким образом, ключи секретов пользователя имеют приоритет над ключами в appsettings.json и appsettings.{Environment}.json.

Дополнительные сведения о хранении паролей или других конфиденциальных данных:

В Azure Key Vault безопасно хранятся секреты приложений ASP.NET Core. Дополнительные сведения см. в статье Поставщик конфигурации Azure Key Vault в ASP.NET Core.

Переменные среды без префикса

К переменным среды без префикса относятся те, что не имеют префикса ASPNETCORE_ или DOTNET_. Для примера можно привести набор шаблонов веб-приложения ASP.NET Core "ASPNETCORE_ENVIRONMENT": "Development" в launchSettings.json. Дополнительные сведения о переменных среды ASPNETCORE_ и DOTNET_:

При использовании конфигурации по умолчаниюEnvironmentVariablesConfigurationProvider загружает конфигурацию из пар "ключ — значение" в переменных среды после чтения appsettings.json, appsettings.{Environment}.json и секретов пользователя. Поэтому значения ключей, считанные из среды, переопределяют значения, считанные из appsettings.json, appsettings.{Environment}.json и секретов пользователя.

Разделитель : не работает с иерархическими ключами переменных среды на всех платформах. __ (двойной символ подчеркивания):

  • Поддерживается всеми платформами. Например, разделитель : не поддерживается Bash, а __ — поддерживается.
  • Автоматически заменяется на :

Следующие команды set:

set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run

Предыдущие параметры среды:

  • Задаются только в процессах, запускаемых из командного окна, в котором они были установлены.
  • Не будут считываться браузерами, запущенными в Visual Studio.

Следующие команды setx можно использовать для задания ключей и значений среды в Windows. В отличие от set, параметры setx сохраняются. /M задает переменную в системной среде. Если параметр /M не используется, задается переменная среды пользователя.

setx MyKey "My key from setx Environment" /M
setx Position__Title Environment_Editor /M
setx Position__Name Environment_Rick /M

Чтобы проверить, что предыдущие команды переопределяют appsettings.json и appsettings.{Environment}.json:

  • С помощью Visual Studio: выход и перезапуск Visual Studio.
  • С помощью интерфейса командной строки: запустите новое командное окно и введите dotnet run.

Вызовите AddEnvironmentVariables со строкой, чтобы указать префикс для переменных среды:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Configuration.AddEnvironmentVariables(prefix: "MyCustomPrefix_");

var app = builder.Build();

В предыдущем коде:

Префикс отделяется при создании пары конфигурации "ключ-значение".

Следующие команды проверяют пользовательский префикс:

set MyCustomPrefix_MyKey="My key with MyCustomPrefix_ Environment"
set MyCustomPrefix_Position__Title=Editor_with_customPrefix
set MyCustomPrefix_Position__Name=Environment_Rick_cp
dotnet run

Конфигурация по умолчанию загружает переменные среды и аргументы командной строки с префиксом DOTNET_ и ASPNETCORE_. Префиксы DOTNET_ и ASPNETCORE_ используются ASP.NET Core для конфигурации узла и приложения, но не для конфигурации пользователя. Дополнительные сведения о конфигурации узла и приложения см. в разделе Универсальный узел .NET.

В Службе приложений Azure выберите Новый параметр приложения на странице Параметры > Конфигурация. Параметры приложения Службы приложений Azure:

  • Шифруются, когда они неактивны, и передаются по зашифрованному каналу.
  • Предоставляются как переменные среды.

Дополнительные сведения см. в разделе Приложения Azure. Переопределение конфигурации приложения с помощью портала Azure.

Сведения о строках подключения к базе данных Azure см. в разделе Префиксы строк подключения.

Именование переменных среды

Имена переменных среды отражают структуру файла appsettings.json. Каждый элемент в иерархии отделяется двойным символом подчеркивания (предпочтительно) или двоеточием. Если структура элемента включает массив, индекс массива должен рассматриваться как дополнительное имя элемента в этом пути. Рассмотрим следующий файл appsettings.json и его эквивалентные значения, представленные в виде переменных среды:

appsettings.json

{
    "SmtpServer": "smtp.example.com",
    "Logging": [
        {
            "Name": "ToEmail",
            "Level": "Critical",
            "Args": {
                "FromAddress": "MySystem@example.com",
                "ToAddress": "SRE@example.com"
            }
        },
        {
            "Name": "ToConsole",
            "Level": "Information"
        }
    ]
}

Переменные среды

setx SmtpServer smtp.example.com
setx Logging__0__Name ToEmail
setx Logging__0__Level Critical
setx Logging__0__Args__FromAddress MySystem@example.com
setx Logging__0__Args__ToAddress SRE@example.com
setx Logging__1__Name ToConsole
setx Logging__1__Level Information

Переменные среды, заданные в созданном файле launchSettings.json

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде. Например, веб-шаблоны ASP.NET Core создают launchSettings.json файл, который задает конфигурацию конечной точки следующим образом:

"applicationUrl": "https://localhost:5001;http://localhost:5000"

При настройке applicationUrl устанавливается переменная среды ASPNETCORE_URLS и переопределяются значения, заданные в среде.

Экранирование переменных среды в Linux

В Linux значения переменных среды URL-адресов нужно экранировать, чтобы их можно было проанализировать с помощью systemd. Используйте средство Linux systemd-escape, которое приостанавливает http:--localhost:5001.

groot@terminus:~$ systemd-escape http://localhost:5001
http:--localhost:5001

Отображение переменных среды

Следующий код позволяет отобразить переменные среды и значения при запуске приложения, что может быть полезно при отладке параметров среды:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

foreach (var c in builder.Configuration.AsEnumerable())
{
    Console.WriteLine(c.Key + " = " + c.Value);
}

Командная строка

При использовании конфигурации по умолчаниюCommandLineConfigurationProvider загружает конфигурацию из пар "ключ-значение" аргументов командной строки после следующих источников конфигурации:

По умолчанию значения конфигурации, заданные для значений конфигурации переопределения в командной строке, задаются для всех остальных поставщиков конфигурации.

Аргументы командной строки

Следующая команда задает ключи и значения с помощью =:

dotnet run MyKey="Using =" Position:Title=Cmd Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью /:

dotnet run /MyKey "Using /" /Position:Title=Cmd /Position:Name=Cmd_Rick

Следующая команда задает ключи и значения с помощью --:

dotnet run --MyKey "Using --" --Position:Title=Cmd --Position:Name=Cmd_Rick

Значение ключа:

  • Должно соответствовать =, или ключ должен иметь префикс -- или /, когда значение следует за пробелом.
  • Является обязательным, если используется параметр =. Например, MySetting=.

В рамках одной и той же команды не смешивайте пары "ключ-значение" аргумента командной строки, которые используют = с парами "ключ-значение" с пробелом.

Сопоставления переключений

Сопоставление параметров позволяет указать логику замены имен ключей. Предоставьте словарь замены параметров для метода AddCommandLine.

В словаре сопоставлений переключений выполняется поиск ключа, который совпадает с ключом, предоставляемым аргументом командной строки. Если ключ в командной строке находится в словаре, значение словаря передается обратно, чтобы установить пару "ключ-значение" в конфигурацию приложения. Сопоставление переключений необходимо для любого ключа командной строки с префиксом из одного дефиса (-).

Правила ключей из словаря сопоставления переключений:

  • Параметры должны начинаться с - или --.
  • Словарь сопоставлений переключений не должен содержать повторяющиеся ключи.

Чтобы использовать словарь сопоставлений параметров, передайте его в вызов AddCommandLine:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var switchMappings = new Dictionary<string, string>()
         {
             { "-k1", "key1" },
             { "-k2", "key2" },
             { "--alt3", "key3" },
             { "--alt4", "key4" },
             { "--alt5", "key5" },
             { "--alt6", "key6" },
         };

builder.Configuration.AddCommandLine(args, switchMappings);

var app = builder.Build();

Выполните следующую команду, чтобы проверить замену ключа:

dotnet run -k1 value1 -k2 value2 --alt3=value2 /alt4=value3 --alt5 value5 /alt6 value6

В следующем коде показаны ключевые значения для замененных ключей:

public class Test3Model : PageModel
{
    private readonly IConfiguration Config;

    public Test3Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        return Content(
                $"Key1: '{Config["Key1"]}'\n" +
                $"Key2: '{Config["Key2"]}'\n" +
                $"Key3: '{Config["Key3"]}'\n" +
                $"Key4: '{Config["Key4"]}'\n" +
                $"Key5: '{Config["Key5"]}'\n" +
                $"Key6: '{Config["Key6"]}'");
    }
}

Для приложений, использующих сопоставления переключений, в вызове CreateDefaultBuilder аргументы передаваться не должны. Вызов команды AddCommandLine метода CreateDefaultBuilder не включает сопоставленные параметры, и нет возможности передать словарь сопоставления параметров в CreateDefaultBuilder. Чтобы решить эту проблему, нужно не передавать аргументы команде CreateDefaultBuilder, а позволить методу AddCommandLine метода ConfigurationBuilder обрабатывать как аргументы, так и словарь сопоставления параметров.

Настройка среды и аргументов командной строки с помощью Visual Studio

Аргументы среды и командной строки можно задать в Visual Studio в диалоговом окне профилей запуска:

  • В Обозревателе решений щелкните проект правой кнопкой мыши и выберите Свойства.
  • Откройте вкладку Отладка > Общие и выберите пункт Открыть пользовательский интерфейс профилей запуска отладки.

Иерархическая модель конфигурации

API конфигурации считывает иерархические данные конфигурации, выполняя преобразование в плоскую структуру иерархических данных с использованием разделителя в ключах конфигурации.

Пример скачивания содержит следующий файл appsettings.json:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "MyKey": "My appsettings.json Value",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

В следующем коде из примера загрузки отображаются некоторые параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Предпочтительный способ чтения иерархических данных конфигурации — использование шаблона параметров. Дополнительные сведения см. в разделе Привязка иерархических данных конфигурации в этом документе.

Методы GetSection и GetChildren доступны для изолирования разделов и дочерних элементов раздела в данных конфигурации. Эти методы описаны далее в разделе GetSection, GetChildren и Exists.

Ключи и значения конфигурации

Ключи конфигурации:

  • Не учитывают регистр. Например ConnectionString и connectionstring обрабатываются как эквивалентные ключи.
  • Если ключ и значение заданы более чем в одном поставщике конфигурации, используется значение из последнего добавленного поставщика. Дополнительные сведения см. в разделе Конфигурация по умолчанию.
  • Иерархические ключи
    • При взаимодействии с API конфигурации разделитель-двоеточие (:) поддерживается на всех платформах.
    • В переменных среды разделитель-двоеточие может не работать на всех платформах. Двойной знак подчеркивания (__) поддерживается на всех платформах и автоматически преобразовывается в двоеточие — :.
    • В Azure Key Vault иерархические ключи используют -- в качестве разделителя. Поставщик конфигурации Azure Key Vault автоматически заменяет -- на : при загрузке секретов в конфигурацию приложения.
  • ConfigurationBinder поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Привязка массива описана в разделе Привязка массива к классу.

Значения конфигурации:

  • Представляют собой строки.
  • Значение NULL не может храниться в конфигурации или быть привязанным к объектам.

Поставщики конфигураций

В следующей таблице показаны поставщики конфигурации, доступные для приложений ASP.NET Core.

Provider Предоставляет конфигурацию из
Поставщик конфигурации Azure Key Vault Azure Key Vault
Поставщик конфигурации приложения Azure Настройка приложения Azure
Поставщик конфигурации командной строки Параметры командной строки
Поставщик пользовательской конфигурации Источник пользователя
Поставщик конфигурации переменных среды Переменные среды
Поставщик конфигурации файла Файлы INI, JSON и XML
Поставщик конфигурации ключа для каждого файла справочных файлов;
Поставщик конфигурации памяти Коллекции оперативной памяти
Секреты пользователя Файл в каталоге профиля пользователя

Источники конфигурации считываются в том порядке, в котором указываются их поставщики конфигурации. Порядок поставщиков конфигурации в коде соответствует приоритетам ваших основных источников конфигурации, требуемых приложением.

Типичная последовательность поставщиков конфигурации.

  1. appsettings.json
  2. appsettings.{Environment}.json
  3. Секреты пользователя
  4. Переменные среды, использующие поставщик конфигурации переменных среды.
  5. Аргументы командной строки, использующие поставщик конфигурации командной строки.

Общепринятой практикой является добавление поставщика конфигурации командной строки последним в ряду поставщиков, чтобы аргументы командной строки могли переопределять конфигурацию, установленную другими поставщиками.

Предыдущая последовательность поставщиков используется в конфигурации по умолчанию.

Префиксы строк подключения

API конфигурации имеет особые правила обработки для четырех переменных среды строки подключения. Эти строки подключения участвуют в настройке строк подключения Azure для среды приложения. Переменные среды с префиксами, указанными в таблице, загружаются в приложение с конфигурацией по умолчанию или если префикс не предоставлен для AddEnvironmentVariables.

Префикс строки подключения Provider
CUSTOMCONNSTR_ Поставщик пользователя
MYSQLCONNSTR_ MySQL
SQLAZURECONNSTR_ База данных SQL Azure
SQLCONNSTR_ SQL Server

Когда переменная среды обнаруживается и загружается в конфигурацию с одним из четырех префиксов, приведенных в таблице, происходит следующее.

  • Ключ конфигурации создается путем удаления префикса переменных среды и добавления ключа раздела конфигурации (ConnectionStrings).
  • Создается новая пара "ключ — значение" конфигурации, которая представляет поставщика подключения базы данных (за исключением CUSTOMCONNSTR_, который не имеет указанного поставщика).
Ключ переменной среды Преобразованный ключ конфигурации Запись конфигурации поставщика
CUSTOMCONNSTR_{KEY} ConnectionStrings:{KEY} Запись конфигурации не создана.
MYSQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: MySql.Data.MySqlClient
SQLAZURECONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient
SQLCONNSTR_{KEY} ConnectionStrings:{KEY} Ключ: ConnectionStrings:{KEY}_ProviderName:
Значение: System.Data.SqlClient

Поставщик конфигурации файла

FileConfigurationProvider является базовым классом для загрузки конфигурации из файловой системы. Следующие поставщики конфигурации являются производными от FileConfigurationProvider:

Поставщик конфигурации INI

IniConfigurationProvider загружает конфигурацию из пары "ключ — значение" INI-файла во время выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
    .AddIniFile($"MyIniConfig.{builder.Environment.EnvironmentName}.ini",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyIniConfig.ini и MyIniConfig.{Environment}.ini переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyIniConfig.ini:

MyKey="MyIniConfig.ini Value"

[Position]
Title="My INI Config title"
Name="My INI Config name"

[Logging:LogLevel]
Default=Information
Microsoft=Warning

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Поставщик конфигурации JSON

Поставщик JsonConfigurationProvider загружает конфигурацию из пар "ключ-значение" файла JSON.

Перегрузки могут указывать:

  • Файл является обязательным или нет.
  • Будет ли перезагружена конфигурация, если файл изменится.

Рассмотрим следующий код:

using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("MyConfig.json",
        optional: true,
        reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Предыдущий код:

  • Настраивает JSпоставщик конфигурации ON для загрузки MyConfig.json файла со следующими параметрами:
    • optional: true: файл является необязательным.
    • reloadOnChange: true : файл перезагружается при сохранении изменений.
  • Считывает поставщики конфигурации по умолчанию перед файлом MyConfig.json . Параметры в MyConfig.json параметре переопределения файла в поставщиках конфигурации по умолчанию, включая поставщика конфигурации переменных среды и поставщика конфигурации командной строки.

Как правило, не рекомендуется использовать специальный файл JSON, переопределяющий значения, заданные в поставщике конфигурации переменных среды и поставщике конфигурации командной строки.

Поставщик конфигурации XML

XmlConfigurationProvider загружает конфигурацию из пары "ключ — значение" XML-файла в среде выполнения.

Следующий код добавляет несколько поставщиков конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
    .AddXmlFile($"MyXMLFile.{builder.Environment.EnvironmentName}.xml",
                optional: true, reloadOnChange: true);

builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В приведенном выше коде параметры в файлах MyXMLFile.xml и MyXMLFile.{Environment}.xml переопределяются параметрами в следующих поставщиках:

Пример скачивания содержит следующий файл MyXMLFile.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <MyKey>MyXMLFile Value</MyKey>
  <Position>
    <Title>Title from  MyXMLFile</Title>
    <Name>Name from MyXMLFile</Name>
  </Position>
  <Logging>
    <LogLevel>
      <Default>Information</Default>
      <Microsoft>Warning</Microsoft>
    </LogLevel>
  </Logging>
</configuration>

В следующем коде из примера загрузки отображаются некоторые из перечисленных выше параметров конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

Повторяющиеся элементы, использующие то же имя элемента, работают, если атрибут name используется для различения элементов.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <section name="section0">
    <key name="key0">value 00</key>
    <key name="key1">value 01</key>
  </section>
  <section name="section1">
    <key name="key0">value 10</key>
    <key name="key1">value 11</key>
  </section>
</configuration>

Следующий код считывает предыдущий файл конфигурации и отображает ключи и значения:

public class IndexModel : PageModel
{
    private readonly IConfiguration Configuration;

    public IndexModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var key00 = "section:section0:key:key0";
        var key01 = "section:section0:key:key1";
        var key10 = "section:section1:key:key0";
        var key11 = "section:section1:key:key1";

        var val00 = Configuration[key00];
        var val01 = Configuration[key01];
        var val10 = Configuration[key10];
        var val11 = Configuration[key11];

        return Content($"{key00} value: {val00} \n" +
                       $"{key01} value: {val01} \n" +
                       $"{key10} value: {val10} \n" +
                       $"{key10} value: {val11} \n"
                       );
    }
}

Атрибуты можно использовать для предоставления значений.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <key attribute="value" />
  <section>
    <key attribute="value" />
  </section>
</configuration>

Предыдущий файл конфигурации загружает следующие ключи с помощью value.

  • key:attribute
  • section:key:attribute

Поставщик конфигурации ключа для каждого файла

KeyPerFileConfigurationProvider использует файлы каталога как пары "ключ — значение" конфигурации. Ключ является именем файла. Значение содержит содержимое файла. Поставщик конфигурации ключа для каждого файла используется в сценариях размещения Docker.

Чтобы активировать конфигурацию ключа для каждого файла, вызовите метод расширения AddKeyPerFile в экземпляре ConfigurationBuilder. Значение параметра directoryPath должно быть абсолютным путем к файлам.

Перегрузки позволяют указать следующее.

  • Action<KeyPerFileConfigurationSource> — делегат, который настраивает источник.
  • Обязательно ли указывать каталог и путь к каталогу.

Двойное подчеркивание (__) используется в качестве разделителя ключа конфигурации в именах файлов. Например, в имени файла Logging__LogLevel__System создается ключ конфигурации Logging:LogLevel:System.

Чтобы указать конфигурацию приложения, при сборке веб-узла вызовите ConfigureAppConfiguration.

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

Поставщик конфигурации памяти

MemoryConfigurationProvider использует коллекцию памяти в качестве пар "ключ — значение" конфигурации.

Следующий код добавляет коллекцию памяти в систему конфигурации:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Configuration.AddInMemoryCollection(Dict);
builder.Configuration.AddEnvironmentVariables();
builder.Configuration.AddCommandLine(args);

builder.Services.AddRazorPages();

var app = builder.Build();

В следующем коде из примера загрузки отображаются перечисленные выше параметры конфигурации:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

В предыдущем коде config.AddInMemoryCollection(Dict) добавляется после поставщиков конфигурации по умолчанию. Пример упорядочения поставщиков конфигурации см. в разделе Поставщик конфигурации JSON.

В разделе Привязка массива вы найдете еще один пример использования MemoryConfigurationProvider.

Конфигурация конечной точки Kestrel

Конфигурация конкретной конечной точки Kestrel переопределяет все межсерверные конфигурации конечной точки. Конфигурации межсерверных конечных точек включают:

Обратите внимание на следующий файл appsettings.json, используемый в веб-приложении ASP.NET Core:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Если предыдущая выделенная разметка используется в веб-приложении ASP.NET Core и приложение запускается в командной строке со следующей конфигурацией межсерверной конечной точки:

dotnet run --urls="https://localhost:7777"

Kestrel привязывается к конечной точке, настроенной специально для Kestrel в файле appsettings.json (https://localhost:9999), а не https://localhost:7777.

Рассмотрим конкретную конечную точку Kestrel, настроенную в качестве переменной среды:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

В предыдущей переменной среды Https является именем конкретной конечной точки Kestrel. Предыдущий файл appsettings.json также определяет Kestrel конкретную конечную точку с именем Https. По умолчанию переменные среды, использующие поставщик конфигурации переменных среды считываются после appsettings.{Environment}.json. Поэтому для конечной точки Https используется предыдущая переменная среды.

GetValue

ConfigurationBinder.GetValue извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

В приведенном выше коде, если NumberKey отсутствует в конфигурации, используется значение по умолчанию 99.

GetSection, GetChildren и Exists

В следующих примерах рассмотрим файл MySubsection.json.

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Следующий код добавляется MySubsection.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MySubsection.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

GetSection

IConfiguration.GetSection возвращает подраздел конфигурации с указанным ключом подраздела.

Следующий код возвращает значения для section1:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Следующий код возвращает значения для section2:subsection0:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

Значение GetSection никогда не возвращает значение null. Если соответствующий раздел не найден, возвращается пустой параметр IConfigurationSection.

Когда GetSection возвращает соответствующий раздел, Value не заполняется. Key и Path возвращаются, если раздел существует.

GetChildren и Exists

Следующий код вызывает IConfiguration.GetChildren и возвращает значения для section2:subsection0:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = "";
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Предыдущие вызовы ConfigurationExtensions.Exists кода для проверки наличия раздела:

Привязка массива

ConfigurationBinder.Bind поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Любой формат массива, который предоставляет сегмент числового ключа способен привязать массив к массиву класса POCO.

Рассмотрим MyArray.jsonпример скачивания:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Следующий код добавляется MyArray.json к поставщикам конфигурации:

var builder = WebApplication.CreateBuilder(args);

builder.Configuration
    .AddJsonFile("MyArray.json",
                 optional: true,
                 reloadOnChange: true);

builder.Services.AddRazorPages();

var app = builder.Build();

Следующий код считывает конфигурацию и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample? _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
       _array = Config.GetSection("array").Get<ArrayExample>();
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }
        string s = String.Empty;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

В предыдущих выходных данных индекс 3 имеет значение value40, соответствующее "4": "value40", в файле MyArray.json. Индексы привязанного массива непрерывны и не привязаны к индексу ключа конфигурации. Модуль привязки конфигурации не поддерживает привязку значений NULL или создание записей NULL в связанных объектах.

Поставщик пользовательской конфигурации

Пример приложения демонстрирует, как создать базовый поставщик конфигурации, который считывает пары "ключ — значение" конфигурации из базы данных, используя Entity Framework (EF).

Поставщик имеет следующие характеристики.

  • База данных в памяти EF используется для демонстрационных целей. Чтобы использовать базу данных, для которой требуется строка подключения, выполните вторичный ConfigurationBuilder, чтобы предоставить строку подключения от другого поставщика конфигурации.
  • Поставщик считывает таблицу базы данных в конфигурации при запуске. Поставщик не запрашивает базу данных для каждого ключа.
  • Функция перезагрузки на изменение не реализована, поэтому обновление базы данных после запуска приложения не влияет на конфигурацию приложения.

Определите сущность EFConfigurationValue для хранения значений конфигурации в базе данных.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; } = String.Empty;
    public string Value { get; set; } = String.Empty;
}

Добавьте EFConfigurationContext в хранилище и обратитесь к настроенным значениям.

EFConfigurationProvider/EFConfigurationContext.cs:

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions<EFConfigurationContext> options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values => Set<EFConfigurationValue>();
}

Создайте класс, реализующий перехватчик IConfigurationSource.

EFConfigurationProvider/EFConfigurationSource.cs:

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) => _optionsAction = optionsAction;

    public IConfigurationProvider Build(IConfigurationBuilder builder) => new EFConfigurationProvider(_optionsAction);
}

Создайте пользовательский поставщик конфигурации путем наследования от ConfigurationProvider. Поставщик конфигурации инициализирует пустую базу данных. Так как конфигурационные ключи не учитывают регистр, словарь, используемый для инициализации базы данных, создается с помощью функции сравнения без учета регистра (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            if (dbContext == null || dbContext.Values == null)
            {
                throw new Exception("Null DB context");
            }
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity-2005
        var configValues =
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                    { "quote1", "I aim to misbehave." },
                    { "quote2", "I swallowed a bug." },
                    { "quote3", "You can't stop the signal, Mal." }
            };

        if (dbContext == null || dbContext.Values == null)
        {
            throw new Exception("Null DB context");
        }

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue
            {
                Id = kvp.Key,
                Value = kvp.Value
            })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Метод расширения AddEFConfiguration позволяет добавить источник конфигурации к ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
               this IConfigurationBuilder builder,
               Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

В следующем коде показано, как использовать настраиваемый EFConfigurationProvider в Program.cs:

//using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddEFConfiguration(
    opt => opt.UseInMemoryDatabase("InMemoryDb"));

var app = builder.Build();

app.Run();

Конфигурация доступа с внедрением зависимостей (DI)

Конфигурацию можно внедрить в службы с помощью внедрения зависимостей (DI) путем разрешения службы IConfiguration:

public class Service
{
    private readonly IConfiguration _config;

    public Service(IConfiguration config) =>
        _config = config;

    public void DoSomething()
    {
        var configSettingValue = _config["ConfigSetting"];

        // ...
    }
}

Сведения о том, как получить доступ к значениям с помощью IConfiguration, см. в разделах GetValue и GetSection, GetChildren и Exists данной статьи.

Конфигурация доступа в RazorPages

В следующем коде отображаются данные конфигурации в RazorPage:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

В следующем коде MyOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(
    builder.Configuration.GetSection("MyOptions"));

var app = builder.Build();

В следующей разметке для разрешения и вывода значений параметров используется директива @injectRazor.

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@using SampleApp.Models
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Доступ к конфигурации в файле представления MVC

В следующем коде отображаются данные конфигурации в представлении MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Доступ к конфигурации в Program.cs

Следующий код получает доступ к конфигурации в файле Program.cs.

var builder = WebApplication.CreateBuilder(args);

var key1 = builder.Configuration.GetValue<string>("KeyOne");

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

var key2 = app.Configuration.GetValue<int>("KeyTwo");
var key3 = app.Configuration.GetValue<bool>("KeyThree");

app.Logger.LogInformation("KeyOne: {KeyOne}", key1);
app.Logger.LogInformation("KeyTwo: {KeyTwo}", key2);
app.Logger.LogInformation("KeyThree: {KeyThree}", key3);

app.Run();

В appsettings.json предыдущем примере:

{
  ...
  "KeyOne": "Key One Value",
  "KeyTwo": 1999,
  "KeyThree": true
}

Настройка параметров с помощью делегата

Параметры, настроенные в делегате, переопределяют значения, заданные в поставщиках конфигурации.

В приведенном ниже коде в контейнер службы добавляется служба IConfigureOptions<TOptions>. Она использует делегат для настройки значений для MyOptions:

using SampleApp.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

builder.Services.Configure<MyOptions>(myOptions =>
{
    myOptions.Option1 = "Value configured in delegate";
    myOptions.Option2 = 500;
});

var app = builder.Build();

Следующий код отображает значения параметров:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

В предыдущем примере значения Option1 и Option2 задаются в файле appsettings.json, а затем переопределяются настроенным делегатом.

Конфигурация узла и приложения

Перед настройкой и запуском приложения настройте и запустите узел. Узел отвечает за запуск приложения и управление временем существования. Как приложение, так и узел настраиваются с использованием поставщиков конфигурации, описанных в этом разделе. Пары "ключ — значение" конфигурации узлов также включаются в конфигурацию приложения. Дополнительные сведения о том, как используются поставщики конфигурации при создании узла и как источники конфигурации влияют на его настройку, см. в статье Основы ASP.NET Core.

Конфигурация узла по умолчанию

Подробные сведения о конфигурации по умолчанию при использовании веб-узла см. в разделе о версии ASP.NET Core 2.2 в этой статье.

  • Конфигурация узла предоставляется из:
  • Конфигурация веб-узла по умолчанию устанавливается (ConfigureWebHostDefaults):
    • Kestrel используется в качестве веб-сервера и настраивается посредством поставщиков конфигурации приложения.
    • Добавьте ПО промежуточного слоя фильтрации узлов.
    • Если переменной среды ASPNETCORE_FORWARDEDHEADERS_ENABLED присвоено значение true, добавьте ПО промежуточного слоя перенаправления заголовков.
    • Включите интеграцию служб IIS.

Прочая конфигурация

Этот раздел относится только к конфигурации приложений. Другие аспекты запуска и размещения приложений ASP.NET Core настраиваются с помощью файлов конфигурации, которые не рассматриваются в этом разделе.

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде.

Дополнительные сведения о переносе конфигурации приложений из более ранних версий ASP.NET см. в разделе "Обновление от ASP.NET до ASP.NET Core".

Добавление конфигурации из внешней сборки

Реализация IHostingStartup позволяет при запуске добавлять в приложение улучшения из внешней сборки вне приложения класса Startup. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Дополнительные ресурсы

Конфигурация конечной точки Kestrel

Конфигурация конкретной конечной точки Kestrel переопределяет все межсерверные конфигурации конечной точки. Конфигурации межсерверных конечных точек включают:

Обратите внимание на следующий файл appsettings.json, используемый в веб-приложении ASP.NET Core:

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

Если предыдущая выделенная разметка используется в веб-приложении ASP.NET Core и приложение запускается в командной строке со следующей конфигурацией межсерверной конечной точки:

dotnet run --urls="https://localhost:7777"

Kestrel привязывается к конечной точке, настроенной специально для Kestrel в файле appsettings.json (https://localhost:9999), а не https://localhost:7777.

Рассмотрим конкретную конечную точку Kestrel, настроенную в качестве переменной среды:

set Kestrel__Endpoints__Https__Url=https://localhost:8888

В предыдущей переменной среды Https является именем конкретной конечной точки Kestrel. Предыдущий файл appsettings.json также определяет Kestrel конкретную конечную точку с именем Https. По умолчанию переменные среды, использующие поставщик конфигурации переменных среды считываются после appsettings.{Environment}.json. Поэтому для конечной точки Https используется предыдущая переменная среды.

GetValue

ConfigurationBinder.GetValue извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип: Этот метод является методом расширения для IConfiguration:

public class TestNumModel : PageModel
{
    private readonly IConfiguration Configuration;

    public TestNumModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var number = Configuration.GetValue<int>("NumberKey", 99);
        return Content($"{number}");
    }
}

В приведенном выше коде, если NumberKey отсутствует в конфигурации, используется значение по умолчанию 99.

GetSection, GetChildren и Exists

В следующих примерах рассмотрим файл MySubsection.json.

{
  "section0": {
    "key0": "value00",
    "key1": "value01"
  },
  "section1": {
    "key0": "value10",
    "key1": "value11"
  },
  "section2": {
    "subsection0": {
      "key0": "value200",
      "key1": "value201"
    },
    "subsection1": {
      "key0": "value210",
      "key1": "value211"
    }
  }
}

Следующий код добавляется MySubsection.json к поставщикам конфигурации:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("MySubsection.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

GetSection

IConfiguration.GetSection возвращает подраздел конфигурации с указанным ключом подраздела.

Следующий код возвращает значения для section1:

public class TestSectionModel : PageModel
{
    private readonly IConfiguration Config;

    public TestSectionModel(IConfiguration configuration)
    {
        Config = configuration.GetSection("section1");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section1:key0: '{Config["key0"]}'\n" +
                $"section1:key1: '{Config["key1"]}'");
    }
}

Следующий код возвращает значения для section2:subsection0:

public class TestSection2Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection2Model(IConfiguration configuration)
    {
        Config = configuration.GetSection("section2:subsection0");
    }

    public ContentResult OnGet()
    {
        return Content(
                $"section2:subsection0:key0 '{Config["key0"]}'\n" +
                $"section2:subsection0:key1:'{Config["key1"]}'");
    }
}

Значение GetSection никогда не возвращает значение null. Если соответствующий раздел не найден, возвращается пустой параметр IConfigurationSection.

Когда GetSection возвращает соответствующий раздел, Value не заполняется. Key и Path возвращаются, если раздел существует.

GetChildren и Exists

Следующий код вызывает IConfiguration.GetChildren и возвращает значения для section2:subsection0:

public class TestSection4Model : PageModel
{
    private readonly IConfiguration Config;

    public TestSection4Model(IConfiguration configuration)
    {
        Config = configuration;
    }

    public ContentResult OnGet()
    {
        string s = null;
        var selection = Config.GetSection("section2");
        if (!selection.Exists())
        {
            throw new System.Exception("section2 does not exist.");
        }
        var children = selection.GetChildren();

        foreach (var subSection in children)
        {
            int i = 0;
            var key1 = subSection.Key + ":key" + i++.ToString();
            var key2 = subSection.Key + ":key" + i.ToString();
            s += key1 + " value: " + selection[key1] + "\n";
            s += key2 + " value: " + selection[key2] + "\n";
        }
        return Content(s);
    }
}

Предыдущие вызовы ConfigurationExtensions.Exists кода для проверки наличия раздела:

Привязка массива

ConfigurationBinder.Bind поддерживает массивы привязки к объектам с помощью массива индексов в ключах конфигурации. Любой формат массива, который предоставляет сегмент числового ключа способен привязать массив к массиву класса POCO.

Рассмотрим MyArray.jsonпример скачивания:

{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}

Следующий код добавляется MyArray.json к поставщикам конфигурации:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("MyArray.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Следующий код считывает конфигурацию и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value00
Index: 1  Value: value10
Index: 2  Value: value20
Index: 3  Value: value40
Index: 4  Value: value50

В предыдущих выходных данных индекс 3 имеет значение value40, соответствующее "4": "value40", в файле MyArray.json. Индексы привязанного массива непрерывны и не привязаны к индексу ключа конфигурации. Модуль привязки конфигурации не поддерживает привязку значений NULL или создание записей NULL в связанных объектах

Следующий код загружает конфигурацию array:entries с помощью метода расширения AddInMemoryCollection:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Следующий код считывает конфигурацию в arrayDictDictionary и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value4
Index: 4  Value: value5

Индекс #3 в связанном объекте содержит данные конфигурации для конфигурационного ключа array:4 и его значения value4. При привязке данных конфигурации, содержащих массив индексов, в ключах конфигурации эти индексы используются для выполнения итерации данных конфигурации при создании объекта. Когда массив ключей конфигурации пропускает один или несколько индексов, в данных конфигурации не может быть сохранено нулевое значение и в связанном объекте не создается нулевая запись.

Отсутствующий элемент конфигурации для индекса #3 может быть предоставлен перед привязкой к экземпляру ArrayExample любым поставщиком конфигурации, который считывает пару "ключ-значение" индекса #3. Рассмотрим следующий Value3.json файл из примера скачивания:

{
  "array:entries:3": "value3"
}

Следующий код включает конфигурацию для Value3.json и arrayDictDictionary:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var arrayDict = new Dictionary<string, string>
        {
            {"array:entries:0", "value0"},
            {"array:entries:1", "value1"},
            {"array:entries:2", "value2"},
            //              3   Skipped
            {"array:entries:4", "value4"},
            {"array:entries:5", "value5"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(arrayDict);
                config.AddJsonFile("Value3.json",
                                    optional: false, reloadOnChange: false);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

Следующий код считывает предыдущую конфигурацию и отображает значения:

public class ArrayModel : PageModel
{
    private readonly IConfiguration Config;
    public ArrayExample _array { get; private set; }

    public ArrayModel(IConfiguration config)
    {
        Config = config;
    }

    public ContentResult OnGet()
    {
        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = null;

        for (int j = 0; j < _array.Entries.Length; j++)
        {
            s += $"Index: {j}  Value:  {_array.Entries[j]} \n";
        }

        return Content(s);
    }
}

Предыдущий код возвращает следующие выходные данные:

Index: 0  Value: value0
Index: 1  Value: value1
Index: 2  Value: value2
Index: 3  Value: value3
Index: 4  Value: value4
Index: 5  Value: value5

Пользовательские поставщики конфигурации не обязаны реализовывать привязку массива.

Поставщик пользовательской конфигурации

Пример приложения демонстрирует, как создать базовый поставщик конфигурации, который считывает пары "ключ — значение" конфигурации из базы данных, используя Entity Framework (EF).

Поставщик имеет следующие характеристики.

  • База данных в памяти EF используется для демонстрационных целей. Чтобы использовать базу данных, для которой требуется строка подключения, выполните вторичный ConfigurationBuilder, чтобы предоставить строку подключения от другого поставщика конфигурации.
  • Поставщик считывает таблицу базы данных в конфигурации при запуске. Поставщик не запрашивает базу данных для каждого ключа.
  • Функция перезагрузки на изменение не реализована, поэтому обновление базы данных после запуска приложения не влияет на конфигурацию приложения.

Определите сущность EFConfigurationValue для хранения значений конфигурации в базе данных.

Models/EFConfigurationValue.cs:

public class EFConfigurationValue
{
    public string Id { get; set; }
    public string Value { get; set; }
}

Добавьте EFConfigurationContext в хранилище и обратитесь к настроенным значениям.

EFConfigurationProvider/EFConfigurationContext.cs:

// using Microsoft.EntityFrameworkCore;

public class EFConfigurationContext : DbContext
{
    public EFConfigurationContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<EFConfigurationValue> Values { get; set; }
}

Создайте класс, реализующий перехватчик IConfigurationSource.

EFConfigurationProvider/EFConfigurationSource.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;

    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
    {
        _optionsAction = optionsAction;
    }

    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_optionsAction);
    }
}

Создайте пользовательский поставщик конфигурации путем наследования от ConfigurationProvider. Поставщик конфигурации инициализирует пустую базу данных. Так как конфигурационные ключи не учитывают регистр, словарь, используемый для инициализации базы данных, создается с помощью функции сравнения без учета регистра (StringComparer.OrdinalIgnoreCase).

EFConfigurationProvider/EFConfigurationProvider.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public class EFConfigurationProvider : ConfigurationProvider
{
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }

    Action<DbContextOptionsBuilder> OptionsAction { get; }

    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();

        OptionsAction(builder);

        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();

            Data = !dbContext.Values.Any()
                ? CreateAndSaveDefaultValues(dbContext)
                : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }

    private static IDictionary<string, string> CreateAndSaveDefaultValues(
        EFConfigurationContext dbContext)
    {
        // Quotes (c)2005 Universal Pictures: Serenity
        // https://www.uphe.com/movies/serenity-2005
        var configValues = 
            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "quote1", "I aim to misbehave." },
                { "quote2", "I swallowed a bug." },
                { "quote3", "You can't stop the signal, Mal." }
            };

        dbContext.Values.AddRange(configValues
            .Select(kvp => new EFConfigurationValue 
                {
                    Id = kvp.Key,
                    Value = kvp.Value
                })
            .ToArray());

        dbContext.SaveChanges();

        return configValues;
    }
}

Метод расширения AddEFConfiguration позволяет добавить источник конфигурации к ConfigurationBuilder.

Extensions/EntityFrameworkExtensions.cs:

// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Configuration;

public static class EntityFrameworkExtensions
{
    public static IConfigurationBuilder AddEFConfiguration(
        this IConfigurationBuilder builder, 
        Action<DbContextOptionsBuilder> optionsAction)
    {
        return builder.Add(new EFConfigurationSource(optionsAction));
    }
}

В следующем коде показано, как использовать настраиваемый EFConfigurationProvider в Program.cs:

// using Microsoft.EntityFrameworkCore;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddEFConfiguration(
                options => options.UseInMemoryDatabase("InMemoryDb"));
        })

Доступ к конфигурации во время запуска

В следующем коде отображаются данные конфигурации в методах Startup:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        Console.WriteLine($"MyKey : {Configuration["MyKey"]}");
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        Console.WriteLine($"Position:Title : {Configuration["Position:Title"]}");

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

Пример доступа к конфигурации с использованием удобных методов запуска см. в разделе Запуск приложения. Удобные методы.

Конфигурация доступа в RazorPages

В следующем коде отображаются данные конфигурации в RazorPage:

@page
@model Test5Model
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

В следующем коде MyOptions добавляется в контейнер службы с помощью интерфейса Configure и привязывается к конфигурации:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(Configuration.GetSection("MyOptions"));

    services.AddRazorPages();
}

В следующей разметке для разрешения и вывода значений параметров используется директива @injectRazor.

@page
@model SampleApp.Pages.Test3Model
@using Microsoft.Extensions.Options
@inject IOptions<MyOptions> optionsAccessor


<p><b>Option1:</b> @optionsAccessor.Value.Option1</p>
<p><b>Option2:</b> @optionsAccessor.Value.Option2</p>

Доступ к конфигурации в файле представления MVC

В следующем коде отображаются данные конфигурации в представлении MVC:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Configuration value for 'MyKey': @Configuration["MyKey"]

Настройка параметров с помощью делегата

Параметры, настроенные в делегате, переопределяют значения, заданные в поставщиках конфигурации.

Настройка параметров с помощью делегата демонстрируется в примере 2 в примере приложения.

В приведенном ниже коде в контейнер службы добавляется служба IConfigureOptions<TOptions>. Она использует делегат для настройки значений для MyOptions:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<MyOptions>(myOptions =>
    {
        myOptions.Option1 = "Value configured in delegate";
        myOptions.Option2 = 500;
    });

    services.AddRazorPages();
}

Следующий код отображает значения параметров:

public class Test2Model : PageModel
{
    private readonly IOptions<MyOptions> _optionsDelegate;

    public Test2Model(IOptions<MyOptions> optionsDelegate )
    {
        _optionsDelegate = optionsDelegate;
    }

    public ContentResult OnGet()
    {
        return Content($"Option1: {_optionsDelegate.Value.Option1} \n" +
                       $"Option2: {_optionsDelegate.Value.Option2}");
    }
}

В предыдущем примере значения Option1 и Option2 задаются в файле appsettings.json, а затем переопределяются настроенным делегатом.

Конфигурация узла и приложения

Перед настройкой и запуском приложения настройте и запустите узел. Узел отвечает за запуск приложения и управление временем существования. Как приложение, так и узел настраиваются с использованием поставщиков конфигурации, описанных в этом разделе. Пары "ключ — значение" конфигурации узлов также включаются в конфигурацию приложения. Дополнительные сведения о том, как используются поставщики конфигурации при создании узла и как источники конфигурации влияют на его настройку, см. в статье Основы ASP.NET Core.

Конфигурация узла по умолчанию

Подробные сведения о конфигурации по умолчанию при использовании веб-узла см. в разделе о версии ASP.NET Core 2.2 в этой статье.

  • Конфигурация узла предоставляется из:
    • Переменные среды с префиксом DOTNET_ (например, DOTNET_ENVIRONMENT), использующие поставщик конфигурации переменных среды. Префикс (DOTNET_) исключается при загрузке пар "ключ — значение" конфигурации.
    • Аргументы командной строки, использующие поставщик конфигурации командной строки.
  • Конфигурация веб-узла по умолчанию устанавливается (ConfigureWebHostDefaults):
    • Kestrel используется в качестве веб-сервера и настраивается посредством поставщиков конфигурации приложения.
    • Добавьте ПО промежуточного слоя фильтрации узлов.
    • Если переменной среды ASPNETCORE_FORWARDEDHEADERS_ENABLED присвоено значение true, добавьте ПО промежуточного слоя перенаправления заголовков.
    • Включите интеграцию служб IIS.

Прочая конфигурация

Этот раздел относится только к конфигурации приложений. Другие аспекты запуска и размещения приложений ASP.NET Core настраиваются с помощью файлов конфигурации, которые не рассматриваются в этом разделе.

Переменные среды, заданные в launchSettings.json переопределении этих наборов в системной среде.

Дополнительные сведения о переносе конфигурации приложений из более ранних версий ASP.NET см. в разделе "Обновление от ASP.NET до ASP.NET Core".

Добавление конфигурации из внешней сборки

Реализация IHostingStartup позволяет при запуске добавлять в приложение улучшения из внешней сборки вне приложения класса Startup. Дополнительные сведения см. в статье Использование начальных сборок размещения в ASP.NET Core.

Дополнительные ресурсы