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