Як отримати доступ до конфігурації в будь-якому класі ASP.NET Core?


127

Я пройшов конфігураційну документацію на ядрі ASP.NET. Документація говорить про те, що ви можете отримати доступ до конфігурації з будь-якої точки програми.

Нижче наведено Startup.cs, створений за шаблоном

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

        if (env.IsEnvironment("Development"))
        {
            // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseApplicationInsightsRequestTelemetry();

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseMvc();
    }
}

Тож у Startup.csналаштуваннях усіх налаштувань Startup.cs також має властивість з назвоюConfiguration

Що я не в змозі зрозуміти, як ви отримуєте доступ до цієї конфігурації в контролері або в будь-якому місці програми? MS рекомендує використовувати шаблон параметрів, але у мене є лише 4-5 пар ключових значень, тому я хотів би не використовувати шаблон параметрів. Я просто хотів мати доступ до конфігурації в додатку. Як ввести його в будь-який клас?


1
Якщо це 4-5 ключових пар значень, ви можете просто ввести ці індивідуальні налаштування. Я б рекомендував цей підхід або схему варіантів для цілей прогнозування. Усі три методи ( в тому числі той , який ви спочатку просили о) перераховані відповіді в наступному можливе дубліката питання: stackoverflow.com/questions/30263681 / ...
stephen.vakil

Щоб отримати доступ до конфігурації як словника з будь-якого місця, перевірте цю відповідь .
Amro

Перевірте тут повний приклад коду.
Arghya C

Якщо ви приїхали сюди, тому що ви намагаєтеся перетворити конфігурацію Framework в конфігурацію CORE, ця відповідь для вас stackoverflow.com/a/56498687/1704458
TS

Відповіді:


148

Оновлення

Використання ASP.NET Core 2.0 автоматично додасть IConfigurationекземпляр вашої програми в контейнер для ін'єкцій залежностей. Це також працює в поєднанні з ConfigureAppConfigurationна WebHostBuilder.

Наприклад:

public static void Main(string[] args)
{
    var host = WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(builder =>
        {
            builder.AddIniFile("foo.ini");
        })
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

Це так само просто, як додати IConfigurationекземпляр до колекції служб як об'єкт singleton у ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
   services.AddSingleton<IConfiguration>(Configuration);

   // ...
}

Де Configurationекземпляр у вашому Startupкласі.

Це дозволяє вводити IConfigurationбудь-який контролер або службу:

public class HomeController
{
   public HomeController(IConfiguration configuration)
   {
      // Use IConfiguration instance
   }
}

4
Mollerna .... а як щодо того, якщо ви хочете вставити конфігурацію в проект окремої бібліотеки класів у рішенні? Намагався, як ця приватна статична IConfiguration _configuration {get; набір; } загальнодоступні версії бази даних (конфігурація IConfiguration) {_configuration = конфігурація; } але _конфігурація завжди є нульовою ... вона ніколи не потрапляє в конструктор
dinotom

2
Це сказало, що проїжджати IConfigurationтак дуже швидко. Набагато краще використовувати шаблон Параметри .
Марк Л.

7
Як отримати доступ до значень із "appsettings.json" безпосередньо у спеціальному класі? Не передаючи дані контролера? Це можливо?
Тадей

2
@HenkMollema Чи можете ви сюди додати приклад? Як би я вводив його в будь-який клас (звідки?).
Тадей

5
@HenkMollema Питання полягало в тому, як вводити в будь-який клас ... а не як вводити в "будь-який клас, вирішений за допомогою ін'єкції залежності". Я думаю, що саме тут відбувається неправильне спілкування ... його клас, швидше за все, не викликається з ланцюга, який починається з Контролера або іншого об'єкта, вирішеного автоматично автоматичним процесом DI.
BVernon

34

Правильний спосіб зробити це:

У .NET Core ви можете вставити параметр IConfigurationяк у свій конструктор Class, і він буде доступний.

public class MyClass 
{
    private IConfiguration configuration;
    public MyClass(IConfiguration configuration)
    {
        ConnectionString = new configuration.GetValue<string>("ConnectionString");
    }

Тепер, коли ви хочете створити екземпляр свого класу, оскільки ваш клас отримує ін'єкцію IConfiguration, ви не зможете просто зробити це new MyClass(), тому що йому потрібен IConfigurationпараметр, введений у конструктор, тому вам потрібно буде ввести свій клас як добре до ланцюга впорскування, що означає два простих кроки:

1) Додати свій клас / ес - де ви хочете використовувати IConfiguration, до IServiceCollectionпо ConfigureServices()методу вStartup.cs

services.AddTransient<MyClass>();

2) Визначте екземпляр - скажімо, в Controllerін'єкцію та введемо його за допомогою конструктора:

public class MyController : ControllerBase
{
    private MyClass _myClass;
    public MyController(MyClass myClass)
    {
        _myClass = myClass;
    }

Тепер ви повинні мати можливість насолоджуватися своїм _myClass.configurationвільним ...

Ще один варіант:

Якщо ви все ще шукаєте спосіб отримати його доступним без введення класів у контролер, тоді ви можете зберігати його в а static class, який ви налаштуєте в Startup.cs, щось на зразок:

public static class MyAppData
{
    public static IConfiguration Configuration;
}

І ваш Startupконструктор повинен виглядати так:

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    MyAppData.Configuration = configuration;
}

Потім використовуйте MyAppData.Configurationбудь-де в своїй програмі.

Не конфронтуйте мене, чому перший варіант - це правильний шлях, я просто бачу, як досвідчені розробники завжди уникають даних про сміття на своєму шляху, і ми добре розуміємо, що це не найкраща практика, щоб постійно зберігати в пам'яті навантаження даних, і це не добре для продуктивності і не для розвитку, і, можливо, також безпечніше мати лише при собі те, що потрібно.


5
Все це введення конфігураційних файлів здається безглуздим / безладним. TY для ідеї статичного класу конфігурації.
Андрій

1
Питання, звичайно, стосувалося доступу до конфігурації будь-якого класу, а не лише до контролера. І хоча з новим розвитком мізерних послуг (мікросервісів) це можна подумати, коли справа стосується міграцій, це великий біль. Ось чому мікрософт повернувся System.Configurationдо CORE назад на трасі. Тепер ви можете отримати доступ до своїх старих хороших app.configs так само, як у добрі старі часи. І я не кажу тут про контролерів. Ми говоримо про компоненти, які мають власні конфігурації
TS

Це дозволяє отримати доступ до будь-якого класу, а не лише до контролера, його просто потрібно імпортувати в контролер, щоб отримати ін'єкцію залежності.
Майєр Шпіцер

1
Будь-який метод працює, і аргументи за або проти кожного є академічними, на мою думку. Я використовував обидва для різних застосунків ... тепер, завдяки вашому надзвичайно легкому другому варіанту. Створити статичний клас досить складно за допомогою DI.
iGanja

Другий метод також допомагає у поширеній проблемі. додаткового коду). Це чудово підходить для того сценарію
Джо Мун

30

Я знаю, що це старе, але з огляду на шаблони IOptions це досить просто здійснити:

  1. Клас із загальнодоступними властивостями get / set, які відповідають налаштуванням у конфігурації

    public class ApplicationSettings
    {
        public string UrlBasePath { get; set; }
    }
  2. зареєструйте ваші налаштування

    public void ConfigureServices(IServiceCollection services)
    {
     ...
     services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
    ...
    }
  3. вводити через IOptions

    public class HomeController
    {
       public HomeController(IOptions<ApplicationSettings> appSettings)
       { ...
        appSettings.Value.UrlBasePath
        ...
        // or better practice create a readonly private reference
        }
     }

Я не впевнений, чому ви не просто зробите це.



2
Як отримати доступ до значень із "appsettings.json" безпосередньо у спеціальному класі?
Тадей

2
@JedatKinports вам потрібно додати Nuget-залежності Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.Binderа Microsoft.Extensions.Configuration.Jsonпотім завантажувати appsettings.jsonфайл на зразок var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();..і також потрібно переконатися, що appsettings.jsonкопія у вихідний каталог встановлена ​​наcopy always
LP13

7

Існує також можливість зробити configurationстатичну в startup.cs, щоб те, що ви можете отримати доступ до неї з будь-якого місця з легкістю, статичні змінні зручно так!

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

internal static IConfiguration Configuration { get; private set; }

Це робить конфігурацію доступною в будь-якому місці, використовуючи Startup.Configuration.GetSection...Що може піти не так?


6

Я зараз це роблю так:

// Requires NuGet package Microsoft.Extensions.Configuration.Json

using Microsoft.Extensions.Configuration;
using System.IO;

namespace ImagesToMssql.AppsettingsJson
{
    public static class AppSettingsJson
    {           
        public static IConfigurationRoot GetAppSettings()
        {
            string applicationExeDirectory = ApplicationExeDirectory();

            var builder = new ConfigurationBuilder()
            .SetBasePath(applicationExeDirectory)
            .AddJsonFile("appsettings.json");

            return builder.Build();
        }

        private static string ApplicationExeDirectory()
        {
            var location = System.Reflection.Assembly.GetExecutingAssembly().Location;
            var appRoot = Path.GetDirectoryName(location);

            return appRoot;
        }
    }
}

І тоді я використовую це там, де мені потрібно отримати дані з файлу appsettings.json:

var appSettingsJson = AppSettingsJson.GetAppSettings();
// appSettingsJson["keyName"]

3

Я переглянув зразок шаблону варіантів і побачив таке:

public class Startup
{
    public Startup(IConfiguration config)
    {
        // Configuration from appsettings.json has already been loaded by
        // CreateDefaultBuilder on WebHost in Program.cs. Use DI to load
        // the configuration into the Configuration property.
        Configuration = config;
    }
...
}

Додаючи Iconfiguration в конструктор мого класу, я міг отримати доступ до параметрів конфігурації через DI.

Приклад:

public class MyClass{

    private Iconfiguration _config;

    public MyClass(Iconfiguration config){
        _config = config;
    }

    ... // access _config["myAppSetting"] anywhere in this class
}

Чи працює це, не чітко згадуючи MyClass в Startup.cs, щось подібне? services.AddTransient <MyClass> ();
Хрещений батько

Так, насправді слід згадати про класи, які потрібно ввести в Startup.cs, а не навпаки. Але IConfiguration - я думаю, за замовчуванням вже доступна ін'єкція.
Пітер Хемерік

Так, це працює. Я спробував це, після того як зробити коментар і реалізацію конфігурації було введено в IConfiguration.
Хрещеному батькові

1
@netfed Як стверджує Майєр Спітцер у своїй відповіді, звичайно, вам потрібно буде додати MyClass до запуску та ввести його туди, куди вам потрібно, тому вам не потрібно самостійно створювати новий екземпляр MyClass, ви вводити його там, де вам потрібно.
Пітер Хемерік

2

Я знаю, що може бути кілька способів зробити це, я використовую Core 3.1 і шукав оптимальний / більш чистий варіант, і я закінчив це:

  1. Мій клас запуску за замовчуванням
public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}
  1. Мій appsettings.json такий
{
  "CompanySettings": {
    "name": "Fake Co"
  }
}
  1. Мій клас - це контролер API, тому спершу я додав посилання, а потім ввів інтерфейс IConfiguration
using Microsoft.Extensions.Configuration;

public class EmployeeController 
{
    private IConfiguration _configuration;
    public EmployeeController(IConfiguration configuration)
    {
        _configuration = configuration;
    }
}
  1. Нарешті я використав метод GetValue
public async Task<IActionResult> Post([FromBody] EmployeeModel form)
{
    var companyName = configuration.GetValue<string>("CompanySettings:name");
    // companyName = "Fake Co"
}

0

У 8-2017 році Microsoft вийшла System.Configurationдля .NET CORE v4.4. Наразі попередній перегляд v4.5 та v4.6.

Для тих із нас, хто працює над перетворенням .Net Framework на CORE, це важливо. Це дозволяє зберігати та використовувати поточні app.configфайли, доступ до яких можна отримати з будь-якої збірки. Це, мабуть, навіть може бути альтернативоюappsettings.json , оскільки Microsoft усвідомила потребу в цьому. Він працює так само, як і раніше в FW. Є одна відмінність:

У веб-додатках [наприклад ASP.NET CORE WEB API] потрібно використовувати, app.configа не web.config для вашого appSettingsабо configurationSection. Можливо, вам доведеться використовувати, web.configале лише якщо ви розгортаєте свій сайт через IIS. Ви розміщуєте налаштування, специфічні для IISweb.config

Я перевірив це за допомогою DLL netstandard20 DLL та Asp.net Core Web Api, і все працює.


0

Використання шаблону параметрів у ASP.NET Core - це шлях. Я просто хочу додати, якщо вам потрібно отримати доступ до параметрів у вашому startup.cs , рекомендую зробити це так:

CosmosDbOptions.cs:

public class CosmosDbOptions
{
    public string ConnectionString { get; set; }
}

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    // This is how you can access the Connection String:
    var connectionString = Configuration.GetSection(nameof(CosmosDbOptions))[nameof(CosmosDbOptions.ConnectionString)];
}

тож якщо мені подобається цілий підрозділ із десятками значень конфігурацій, до яких мені потрібно отримати доступ у ConfigureServices, то мені потрібно це зробити для всіх них? Чи немає іншого способу зробити це за допомогою шаблону IOptions? Мені потрібно ввести це статичним методом розширення, де я налаштовую свою масову транзитну шину. Крім того, що про цю пропозицію від Microsoft про невикористання IOptions шаблону в ConfigureServices docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration / ...
Kuldeep

Я не використовую IOPtions у ConfigureService тут ...
Мартін Брандл

-3

Я маю прочитати власні параметри при запуску.
Це повинно бути там перед запуском WebHost (оскільки мені потрібен "прослуховувати" URL / IP і порт з файлу параметрів і застосувати його до WebHost). Крім того, мені потрібні налаштування загальнодоступних у всій програмі.

Після деякого пошуку (не знайдено повного прикладу, лише фрагменти) та після різних спроб та помилок, я вирішив зробити це "по-старому" із власним файлом .ini.
Отже, якщо ви хочете використовувати свій власний файл .ini та / або встановіть "для прослуховування URL / IP" власний та / або потрібні налаштування загальнодоступних, це для вас ...

Повний приклад, дійсний для ядра 2.1 (mvc):

Створіть .ini-файл - приклад:

[Startup]
URL = http://172.16.1.201:22222
[Параметр]
* Dummy1 = gew7623
Dummy1 = true
Dummy2 = 1

при цьому Dummyx включається лише як приклад для інших типів дати, крім рядка (а також для перевірки випадку "неправильний параметр" (див. код нижче).

Додано файл коду в корінь проекту для зберігання глобальних змінних:

namespace MatrixGuide
{
    public static class GV
    {
        // In this class all gobals are defined

        static string _cURL;
        public static string cURL // URL (IP + Port) on that the application has to listen
        {
            get { return _cURL; }
            set { _cURL = value; }
        }

        static bool _bdummy1;
        public static bool bdummy1 // 
        {
            get { return _bdummy1; }
            set { _bdummy1 = value; }
        }

        static int _idummy1;
        public static int idummy1 // 
        {
            get { return _idummy1; }
            set { _idummy1 = value; }
        }

        static bool _bFehler_Ini;
        public static bool bFehler_Ini // 
        {
            get { return _bFehler_Ini; }
            set { _bFehler_Ini = value; }
        }

        // add further  GV variables here..
    }
    // Add further classes here... 
}

Змінено код у program.cs (перед CreateWebHostBuilder ()):

namespace MatrixGuide
{
    public class Program
    {
        public static void Main(string[] args)
        {
            // Read .ini file and overtake the contend in globale
            // Do it in an try-catch to be able to react to errors
            GV.bFehler_Ini = false;
            try
            {
                var iniconfig = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddIniFile("matrixGuide.ini", optional: false, reloadOnChange: true)
                .Build();
                string cURL = iniconfig.GetValue<string>("Startup:URL");
                bool bdummy1 = iniconfig.GetValue<bool>("Parameter:Dummy1");
                int idummy2 = iniconfig.GetValue<int>("Parameter:Dummy2");
                //
                GV.cURL = cURL;
                GV.bdummy1 = bdummy1;
                GV.idummy1 = idummy2;
            }
            catch (Exception e)
            {
                GV.bFehler_Ini = true;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("!! Fehler beim Lesen von MatrixGuide.ini !!");
                Console.WriteLine("Message:" + e.Message);
                if (!(e.InnerException != null))
                {
                    Console.WriteLine("InnerException: " + e.InnerException.ToString());
                }

                Console.ForegroundColor = ConsoleColor.White;
            }
            // End .ini file processing
            //
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>() //;
            .UseUrls(GV.cURL, "http://localhost:5000"); // set the to use URL from .ini -> no impact to IISExpress

    }
}

Сюди:

  • Конфігурація мого додатка відокремлена від appsettings.json, і я не маю побічних ефектів побоюватися, якщо MS зміниться в наступних версіях ;-)
  • У мене є налаштування в глобальних змінних
  • Я можу встановити "прослуховувати URL-адресу" для кожного пристрою, програма запуску програми (мій розробник, інтранет-сервер та Інтернет-сервер)
  • Я можу деактивувати налаштування старим способом (просто встановіть * раніше)
  • Я можу реагувати, якщо у файлі .ini щось не так (наприклад, невідповідність типу)
    Якщо - наприклад - встановлено неправильний тип (наприклад, активізовано * Dummy1 = gew7623 замість Dummy1 = true), хост показує червоний інформація на консолі (включаючи виняток), і я можу реагувати також у додатку (GV.bFehler_Ini ist встановлено як true, якщо є помилки з .ini)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.