Подтвердить что ты не робот

Как получить доступ к Конфигурации в любом классе в ASP.NET Core?

Я просмотрел конфигурационную документацию в ядре 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 пар ключ-значение, поэтому я бы не хотел использовать шаблон опций. Я просто хотел иметь доступ к Конфигурации в приложении. Как это сделать в любом классе?

4b9b3361

Ответ 1

Обновить

Использование 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 в коллекцию сервисов, как одноэлементный объект в ConfigureServices:

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

   // ...
}

Где Configuration - это экземпляр в вашем классе Startup.

Это позволяет вам внедрять IConfiguration в любой контроллер или службу:

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

Ответ 2

Я знаю, что это старый, но с учетом того, что шаблоны IOptions относительно просты в реализации:

  • Класс с общедоступными свойствами get/set, которые соответствуют настройкам конфигурации

    public class ApplicationSettings
    {
        public string UrlBasePath { get; set; }
    }
    
  • зарегистрируйте свои настройки

    public void ConfigureServices(IServiceCollection services)
    {
     ...
     services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
    ...
    }
    
  • ввод с помощью IOptions

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

Я не уверен, почему вы не просто это сделаете.

Ответ 3

Правильный способ сделать это:

В .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 в 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 любом месте вашей программы.

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

Ответ 4

Я посмотрел в образец шаблона параметров и увидел это:

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
}

Ответ 5

Я делаю это сейчас так:

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

Ответ 6

Также есть возможность сделать статическую configuration в configuration startup.cs, чтобы удобные статические переменные были удобны, да!

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

internal static IConfiguration Configuration { get; private set; }

Это делает конфигурацию доступной где угодно, используя Startup.Configuration.GetSection... Что может пойти не так?

Ответ 7

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

Я протестировал его с netstandard20 DLL и Asp.net Core Web Api, и все это работает.

Ответ 8

Я должен читать собственные параметры при запуске.
Это должно быть до запуска WebHost (так как мне нужно "прослушать" url/IP и порт из файла параметров и применить его к WebHost). Далее мне нужны общедоступные настройки во всем приложении.

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

Полный пример, действительный для ядра 2.1 (MVC):

Создайте .ini файл - пример:

[Запускать]
URL = http://172.16.1.201:22222
[Параметр]
* Dummy1 = gew7623
Dummy1 = верно
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 = true активирован * Dummy1 = gew7623), хост отображает красную информацию на консоли (включая исключение), и я могу реагировать и в приложении (GV.bFehler_Ini is is true, если есть ошибки с .ini)