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

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

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

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

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

Просмотреть или скачать образец кода (как скачивать)

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

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

var builder = WebApplication.CreateBuilder(args);

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

  1. ChainedConfigurationProvider : добавляет существующий IConfiguration в качестве источника. В случае конфигурации по умолчанию добавляет конфигурацию узла и задает ее в качестве первого источника для конфигурации приложения.
  2. Файл appsettings.json, использующий поставщик конфигурации JSON.
  3. Файл appsettings. Environment .json, использующий поставщик конфигурации JSON. Например, appsettings.Production_._json и appsettings.Development _._json.
  4. Секреты приложения, когда приложение выполняется в среде Development.
  5. Переменные среды, использующие поставщик конфигурации переменных среды.
  6. Аргументы командной строки, использующие поставщик конфигурации командной строки.

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

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

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

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);
    }
}

appsettings.json

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

{
    "Position": {
        "Title": "Редактор",
        "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 добавляется в контейнер службы с помощью интерфейса <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.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;
        }
    }
}

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

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. Рекомендуется, чтобы приложения следовали соглашению об именовании для создания методов расширения в пространстве имен Microsoft.Extensions.DependencyInjection. Создание методов расширения в пространстве имен Microsoft.Extensions.DependencyInjection:

  • Инкапсулирует группы регистраций служб.
  • Предоставляет удобный доступ к службе с помощью IntelliSense.

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

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

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

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

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

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

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

При использовании конфигурации по умолчанию 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 и перезапустите ее.
  • В CLI: Откройте новое командное окно и введите 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();

var config = app.Services.GetRequiredService<IConfiguration>();

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

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

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

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

аргументов командной строки;

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

dotnet run MyKey="My key from command line" 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": "Редактор",
        "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.

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

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

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

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

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

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

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

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

Префикс строки подключения Поставщик
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-файла во время выполнения.

Следующий код очищает все поставщики конфигурации и добавляет несколько поставщиков конфигурации: [!code-csharp]

В приведенном выше коде параметры в 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.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddJsonFile("MyConfig.json",
                       optional: true,
                       reloadOnChange: true);
});

builder.Services.AddRazorPages();

var app = builder.Build();

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

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

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

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

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

var builder = WebApplication.CreateBuilder(args);

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    var env = hostingContext.HostingEnvironment;

    config.AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
          .AddXmlFile($"MyXMLFile.{env.EnvironmentName}.xml",
                         optional: true, reloadOnChange: true);

    config.AddEnvironmentVariables();

    if (args != null)
    {
        config.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.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    config.AddInMemoryCollection(Dict);

    config.AddEnvironmentVariables();

    if (args != null)
    {
        config.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<T> извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип:

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.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.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.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.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()
    {
        if (_array == null)
        {
            throw new ArgumentNullException(nameof(_array));
        }

        _array = Config.GetSection("array").Get<ArrayExample>();
        string s = String.Empty;

        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 в связанных объектах.

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

Пример приложения демонстрирует, как создать базовый поставщик конфигурации, который считывает пары "ключ — значение" конфигурации из базы данных, используя 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
        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();

Конфигурация доступа в 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();

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

@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"]

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

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

В приведенном ниже коде в контейнер службы добавляется служба 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;
  • конфигурация приложения Azure;
  • аргументов командной строки;
  • пользовательские поставщики, установленные или созданные;
  • справочных файлов;
  • объектов .NET в памяти;

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

Просмотреть или скачать образец кода (как скачивать)

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

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

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

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

  1. ChainedConfigurationProvider : добавляет существующий IConfiguration в качестве источника. В случае конфигурации по умолчанию добавляет конфигурацию узла и задает ее в качестве первого источника для конфигурации приложения.
  2. Файл appsettings.json, использующий поставщик конфигурации JSON.
  3. Файл appsettings. Environment .json, использующий поставщик конфигурации JSON. Например, appsettings.Production_._json и appsettings.Development _._json.
  4. Секреты приложения, когда приложение выполняется в среде Development.
  5. Переменные среды, использующие поставщик конфигурации переменных среды.
  6. Аргументы командной строки, использующие поставщик конфигурации командной строки.

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

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

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

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);
    }
}

appsettings.json

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

{
    "Position": {
        "Title": "Редактор",
        "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; }
    public string Name { get; set; }
}

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

  • Должен быть неабстрактным с открытым конструктором без параметров.
  • Все открытые свойства чтения и записи типа привязаны.
  • Поля не привязаны. В приведенном выше коде свойство 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 добавляется в контейнер службы с помощью интерфейса <xref:Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure_> и привязывается к конфигурации:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(Configuration.GetSection(
                                        PositionOptions.Position));
    services.AddRazorPages();
}

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

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 в этом документе.

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

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

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(
        Configuration.GetSection(PositionOptions.Position));
    services.Configure<ColorOptions>(
        Configuration.GetSection(ColorOptions.Color));

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

    services.AddRazorPages();
}

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

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;
        }
    }
}

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddConfig(Configuration)
            .AddMyDependencyGroup();

    services.AddRazorPages();
}

Примечание. Каждый метод расширения services.Add{GROUP_NAME} добавляет и, возможно, настраивает службы. Например, AddControllersWithViews добавляет контроллеры MVC служб с необходимыми представлениями, а AddRazorPages — службы, требуемые для работы Razor Pages. Рекомендуется, чтобы приложения следовали соглашению об именовании для создания методов расширения в пространстве имен Microsoft.Extensions.DependencyInjection. Создание методов расширения в пространстве имен Microsoft.Extensions.DependencyInjection:

  • Инкапсулирует группы регистраций служб.
  • Предоставляет удобный доступ к службе с помощью IntelliSense.

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

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

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

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

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

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

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

При использовании конфигурации по умолчанию 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 и перезапустите ее.
  • В CLI: Откройте новое командное окно и введите dotnet run.

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

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.AddEnvironmentVariables(prefix: "MyCustomPrefix_");
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

В приведенном выше коде:

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

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

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

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

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

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var config = host.Services.GetRequiredService<IConfiguration>();

    foreach (var c in config.AsEnumerable())
    {
        Console.WriteLine(c.Key + " = " + c.Value);
    }
    host.Run();
}

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

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

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

аргументов командной строки;

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

dotnet run MyKey="My key from command line" 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:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

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

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddCommandLine(args, switchMappings);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

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

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"]}'");
    }
}

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

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

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

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

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

Вкладка "Отладка" в VS

В Visual Studio 2019 версии 16.10 (предварительная версия 4) и выше настройка среды и аргументов командной строки выполняется в пользовательском интерфейсе профилей запуска:

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

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

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

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

{
    "Position": {
        "Title": "Редактор",
        "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.

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

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

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

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

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

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

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

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

Префикс строки подключения Поставщик
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-файла во время выполнения.

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

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.Sources.Clear();

                var env = hostingContext.HostingEnvironment;

                config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true)
                      .AddIniFile($"MyIniConfig.{env.EnvironmentName}.ini",
                                     optional: true, reloadOnChange: true);

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

В приведенном выше коде параметры в 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-файла.

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

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

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

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("MyConfig.json", 
                    optional: true, 
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

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

Обычно не требуется, чтобы пользовательские файлы 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.Sources.Clear();

                var env = hostingContext.HostingEnvironment;

                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", 
                                     optional: true, reloadOnChange: true);

                config.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true)
                      .AddJsonFile($"MyConfig.{env.EnvironmentName}.json",
                                     optional: true, reloadOnChange: true);

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

В приведенном выше коде параметры в файлах MyConfig.json и MyConfig.Environment.json:

Пример загрузки содержит следующий файл MyConfig.json:

{
    "Position": {
        "Title": "Заголовок моей конфигурации",
        "Name": "My Config Smith"
    },
    "MyKey": "MyConfig.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}");
    }
}

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

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

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

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.Sources.Clear();

                var env = hostingContext.HostingEnvironment;

                config.AddXmlFile("MyXMLFile.xml", optional: true, reloadOnChange: true)
                      .AddXmlFile($"MyXMLFile.{env.EnvironmentName}.xml",
                                     optional: true, reloadOnChange: true);

                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

В приведенном выше коде параметры в 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 использует коллекцию памяти в качестве пар "ключ — значение" конфигурации.

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

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

        return Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddInMemoryCollection(Dict);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

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

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<T> извлекает одно значение из конфигурации с указанным ключом и преобразует его в указанный тип:

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>();
            });
    }
}

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

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 и arrayDict Dictionary:

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
        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();
}

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

@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.

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