Configuration.GetSection всегда возвращает ноль

Каждый раз звоню Configuration.GetSection, Value свойство возвращаемого объекта всегда равно нулю.

мой Startup конструктор

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();

    this.Configuration = builder.Build();
}

мой ConfigureServices метод

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<SqliteSettings>(opts => Configuration.GetSection("SqliteSettings").Bind(opts));

    services.AddOptions();

    services.AddMvc();
}

мой appsettings.json

{
  "SqliteSettings": {
    "DataSource": "C:\\db.sqlite",
    "NewDatabase": true,
    "Version": 3
  }
}

Класс, который я использую для определения SqliteSettings

public class SqliteSettings
{
    public string DataSource { get; set; }

    public bool? NewDatabase { get; set; }

    public int? Version { get; set; }

    public string Password { get; set; }

    public long? CacheSize { get; set; }

    // More properties
}

Я подумал, что JSON может потребоваться иметь одинаковое количество свойств для сопоставления, или это может быть связано с определениями типов данных, но, возможно, они совершенно не связаны.

16 ответов

Решение

Просто измените свой ConfigureServices способ быть похожим на следующий

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();

    services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));

    services.AddMvc();
}

И это должно работать.

Согласно Документам Microsoft: "Когда GetSection возвращает соответствующий раздел, значение не заполняется. Ключ и путь возвращаются, когда раздел существует".

Если вы хотите увидеть значения этого раздела, вам нужно вызвать метод GetChildren(): Configuration.GetSection("SqliteSettings").GetChildren();

Или вы можете использовать:Configuration.GetSection("SqliteSettings").Get<SqliteSettings>(), JSON не обязательно должен иметь одинаковое количество свойств для сопоставления. Для несопоставленных свойств, допускающих значение NULL, будет установлено значение NULL, а для свойств, не имеющих значения NULL, будут установлены значения по умолчанию (например, для int будет установлено значение 0)

  1. Щелкните правой кнопкой мыши на appsettings.json и перейдите в Свойства.
  2. Выберите Копировать в выходной каталог = Копировать всегда.

Если все остальные ответы не устраняют проблему, другой причиной может быть то, что свойства класса Options являются частными (или не имеют доступных сеттеров).

Моя проблема заключалась в том, что экземпляр объекта метода .bind() не был инициализирован.

      services.Configure<SqliteSettings>(opts => Configuration.GetSection("SqliteSettings").Bind(opts));

Итак, перед вызовом .bind(opts); Я инициализировал значение:

      SqlliteSettings opts = new SqliteSettings();

Привязал переменную локальных настроек:

      Configuration.GetSection(AppSettingsSectionName).Bind(opts);

И сделал регистрацию контейнера отдельно:

      services.Configure<AppSettings>(Configuration.GetSection("SqlliteSettings"));

Это решило проблему, поскольку метод .Bind () просто вернет значение null, если предоставленный экземпляр имеет значение null.

Это работало для меня в консольном приложении

var conncetionString = config["ConnectionStrings:DefaultConnection"]

Убедитесь, что у вашего объекта конфигурации есть средства доступа к свойствам, иначе он не будет правильно привязан. Знание этого сэкономило бы мне 2 часа сегодня.

      public class MyConfiguration
{
        public string ConfigurationOption1; // BAD
        public string ConfigurationOption2 { get; set; } // GOOD
}

В моем случае я использовал VS Code и .net core 3.x webapp.

Я столкнулся с аналогичной проблемой: GetSection() или Configuraton["Section:KeyName"] возвращал значение null, я проверил GetSection(). Exists (), который также вернул false.

Итак, я попытался добавить configbuilder внутри ConfigureServices, который помог мне это исправить,

        public void ConfigureServices(IServiceCollection services)
  {
      //Initialize the builder 
      var builder = new ConfigurationBuilder()
                    .SetBasePath(Environment.CurrentDirectory)
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true)//To specify environment
                    .AddEnvironmentVariables();//You can add if you need to read environment variables.

      //Build the configuration
      IConfiguration Configuration = builder.Build();

       
      services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));
      //Similar to below 
      //services.Configure<EntityClass>(Configuration.GetSection("EntityConfigSection"));
      
  }

Примечание. Убедитесь, что значение cwd и program в .VScode / launch.json имеет правильные значения. Код выбирает текущий рабочий каталог из значения cwd, поэтому нам нужно убедиться, что он установлен правильно.

      {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "X.X.X",
"configurations": [
    {
        "name": ".NET Core Launch (web)",
        "type": "coreclr",
        "request": "launch",
        "preLaunchTask": "build",
        "program": "${workspaceFolder}/<ProjectLocation>/bin/<BuildType>/<Version>/<ProjectDll>",
        "args": [],
        "cwd": "${workspaceFolder}/<ProjectLocation>",
        "stopAtEntry": false,
        "serverReadyAction": {
            "action": "openExternally",
            "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
        },
        "env": {
            "ASPNETCORE_ENVIRONMENT": "Development"
        },
        "sourceFileMap": {
            "/Views": "${workspaceFolder}/Views"
        }
    }

]}

var serviceProvider = services.BuildServiceProvider();

Должны прийти после всех услуг. Настроить звонки.

Если ваша инъекция зависимости не работает, и вы пришли к выводу, что этот метод является проблемой после его отладки, это не так!

Для регистрации достаточно:

      services.Configure<SqliteSettings>(Configuration.GetSection("SqliteSettings"));

Вы должны ввести свой класс конфигурации в интерфейс IOptions . Это решит проблему DI. Я потратил несколько часов на эту проблему, надеюсь, это поможет кому-то другому.

Убедитесь, что вы случайно не вложили свои переменные в значения по умолчанию. Loggingобъект. Я вставлял всевозможные переменные в скобки неправильного уровня (но это было случайно правильно в appsettings.json по умолчанию), что приводило к загадочным отсутствием ключей / значений.

В моем случае для Web Api Core 2.1 я нуждался в этом в корневой папке проекта. Та же папка, что и Startup.cs, Program.cs.

Попробуйте добавить ConfigurationProvider в ConfigurationBuilder.

Конфигурация приложения предоставляется из:

  • appsettings.json с помощью провайдера конфигурации файлов.
  • appsettings. {Environment}.json с использованием поставщика конфигурации файлов.

Убедитесь, что вы добавили код в правильный файл appsettings.json. Может быть несколько файлов appsettings.json, таких как appsettings.Development.json, appsettings.QA.json, в зависимости от проекта и, следовательно, в зависимости от среды, ваш код будет выполнен.

Если у вас есть файл appsettings.Development.json, убедитесь, что настройки "ConnectionStrings:DefaultConnection" находятся в файлах appsettings.Development.json и appsettings.json.

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

Другие вопросы по тегам