简体   繁体   English

如何访问 ASP.NET Core 中任何类中的配置?

[英]How do I access Configuration in any class in ASP.NET Core?

I have gone throughconfiguration documentation on ASP.NET core.我已经阅读了有关 ASP.NET 核心的配置文档 Documentation says you can access configuration from anywhere in the application.文档说您可以从应用程序的任何位置访问配置。

Below is Startup.cs created by template下面是模板创建的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();
    }
}

So in Startup.cs we configure all the settings, Startup.cs also has a property named Configuration所以在Startup.cs中我们配置所有的设置,Startup.cs还有一个名为Configuration的属性

What I'm not able to understand how do you access this configuration in controller or anywhere in the application?我无法理解您如何在控制器或应用程序的任何地方访问此配置? MS is recommending to use options pattern but I have only 4-5 key-value pairs so I would like not to use options pattern. MS 建议使用选项模式,但我只有 4-5 个键值对,所以我不想使用选项模式。 I just wanted to have access to Configuration in application.我只是想访问应用程序中的配置。 How do I inject it in any class?我如何在任何课程中注入它?

Update更新

Using ASP.NET Core 2.0 will automatically add the IConfiguration instance of your application in the dependency injection container.使用 ASP.NET Core 2.0 会自动将应用程序的IConfiguration实例添加到依赖项注入容器中。 This also works in conjunction with ConfigureAppConfiguration on the WebHostBuilder .这也可以与WebHostBuilder上的ConfigureAppConfiguration结合使用。

For example:例如:

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

    host.Run();
}

It's just as easy as adding the IConfiguration instance to the service collection as a singleton object in ConfigureServices :就像将IConfiguration实例作为ConfigureServices中的单例对象添加到服务集合一样简单:

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

   // ...
}

Where Configuration is the instance in your Startup class.其中ConfigurationStartup类中的实例。

This allows you to inject IConfiguration in any controller or service:这允许您在任何控制器或服务中注入IConfiguration

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

The right way to do it:正确的做法:

In .NET Core you can inject the IConfiguration as a parameter into your Class constructor, and it will be available.在 .NET Core 中,您可以将IConfiguration作为参数注入到您的 Class 构造函数中,并且它将可用。

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

Now, when you want to create an instance of your class, since your class gets injected the IConfiguration , you won't be able to just do new MyClass() , because it needs a IConfiguration parameter injected into the constructor, so, you will need to inject your class as well to the injecting chain, which means two simple steps:现在,当你想创建你的类的一个实例时,因为你的类被注入了IConfiguration ,你将不能只做new MyClass() ,因为它需要一个IConfiguration参数注入到构造函数中,所以,你会需要将您的类也注入到注入链中,这意味着两个简单的步骤:

1) Add your Class/es - where you want to use the IConfiguration , to the IServiceCollection at the ConfigureServices() method in Startup.cs 1) 添加你的类/es - 你想使用IConfiguration的地方,到Startup.csConfigureServices()方法的IServiceCollection

services.AddTransient<MyClass>();

2) Define an instance - let's say in the Controller , and inject it using the constructor: 2)定义一个实例 - 让我们在Controller中说,并使用构造函数注入它:

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

Now you should be able to enjoy your _myClass.configuration freely...现在你应该可以自由地享受你的_myClass.configuration ......

Another option:另外一个选择:

If you are still looking for a way to have it available without having to inject the classes into the controller, then you can store it in a static class , which you will configure in the Startup.cs , something like:如果您仍在寻找一种无需将类注入控制器即可使用它的方法,那么您可以将其存储在static class中,您将在Startup.cs中对其进行配置,例如:

public static class MyAppData
{
    public static IConfiguration Configuration;
}

And your Startup constructor should look like this:您的Startup构造函数应如下所示:

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

Then use MyAppData.Configuration anywhere in your program.然后在程序的任何位置使用MyAppData.Configuration

Don't confront me why the first option is the right way, I can just see experienced developers always avoid garbage data along their way, and it's well understood that it's not the best practice to have loads of data available in memory all the time, neither is it good for performance and nor for development, and perhaps it's also more secure to only have with you what you need.不要问我为什么第一个选项是正确的方法,我可以看到有经验的开发人员总是在他们的过程中避免垃圾数据,而且众所周知,内存中始终有大量可用数据并不是最佳实践,这对性能和开发都没有好处,也许只带你需要的东西也更安全。

I know this is old but given the IOptions patterns is relatively simple to implement:我知道这是旧的,但考虑到 IOptions 模式实现起来相对简单:

  1. Class with public get/set properties that match the settings in the configuration具有与配置中的设置匹配的公共获取/设置属性的类

    public class ApplicationSettings { public string UrlBasePath { get; set; } }
  2. register your settings注册您的设置

    public void ConfigureServices(IServiceCollection services) {... services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings")); ... }
  3. inject via IOptions通过 IOptions 注入

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

I'm not sure why you wouldn't just do this.我不确定你为什么不这样做。

There is also an option to make configuration static in startup.cs so that what you can access it anywhere with ease, static variables are convenient huh!还有一个选项可以在 startup.cs 中使configuration静态化,这样你就可以轻松地在任何地方访问它,静态变量很方便啊!

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

internal static IConfiguration Configuration { get; private set; }

This makes configuration accessible anywhere using Startup.Configuration.GetSection... What can go wrong?这使得使用Startup.Configuration.GetSection...可能会出什么问题?

I'm doing it like this at the moment:我现在是这样做的:

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

And then I use this where I need to get the data from the appsettings.json file:然后我在需要从 appsettings.json 文件获取数据的地方使用它:

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

I know there may be several ways to do this, I'm using Core 3.1 and was looking for the optimal/cleaner option and I ended up doing this:我知道可能有几种方法可以做到这一点,我正在使用 Core 3.1 并正在寻找最佳/更清洁的选项,我最终这样做了:

  1. My startup class is as default我的启动类是默认的
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. My appsettings.json is like this我的 appsettings.json 是这样的
{
  "CompanySettings": {
    "name": "Fake Co"
  }
}

  1. My class is an API Controller, so first I added the using reference and then injected the IConfiguration interface我的类是一个 API 控制器,所以首先我添加了 using 引用,然后注入了 IConfiguration 接口
using Microsoft.Extensions.Configuration;

public class EmployeeController 
{
    private IConfiguration _configuration;
    public EmployeeController(IConfiguration configuration)
    {
        _configuration = configuration;
    }
}
  1. Finally I used the GetValue method最后我使用了 GetValue 方法
public async Task<IActionResult> Post([FromBody] EmployeeModel form)
{
    var companyName = configuration.GetValue<string>("CompanySettings:name");
    // companyName = "Fake Co"
}

I looked into the options pattern sample and saw this:我查看了选项模式示例并看到了这个:

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

When adding Iconfiguration in the constructor of my class, I could access the configuration options through DI.在类的构造函数中添加 Iconfiguration 时,我可以通过 DI 访问配置选项。

Example:例子:

public class MyClass{

    private Iconfiguration _config;

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

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

In 8-2017 Microsoft came out with System.Configuration for .NET CORE v4.4. 2017 年 8 月,Microsoft 推出了System.Configuration for .NET CORE v4.4。 Currently v4.5 and v4.6 preview. 目前 v4.5和 v4.6 预览。

For those of us, who works on transformation from.Net Framework to CORE, this is essential.对于我们这些致力于从 .Net Framework 到 CORE 的转换的人来说,这是必不可少的。 It allows to keep and use current app.config files, which can be accessed from any assembly.它允许保留和使用当前的app.config文件,可以从任何程序集访问这些文件。 It is probably even can be an alternative to appsettings.json , since Microsoft realized the need for it.它甚至可能是appsettings.json的替代品,因为微软意识到了对它的需求。 It works same as before in FW.它在 FW 中的工作方式与以前相同。 There is one difference:有一个区别:

In the web applications, [eg ASP.NET CORE WEB API] you need to use app.config and not web.config for your appSettings or configurationSection .在 Web 应用程序中,[例如 ASP.NET CORE WEB API] 您需要为appSettingsconfigurationSection使用app.config不是web.config 。 You might need to use web.config but only if you deploying your site via IIS.您可能需要使用web.config ,但前提是您通过 IIS 部署站点。 You place IIS-specific settings into web.config您将特定于 IIS 的设置放入web.config

I've tested it with netstandard20 DLL and Asp.net Core Web Api and it is all working.我已经使用netstandard20 DLL 和Asp.net Core Web Api对其进行了测试,一切正常。

Using the Options pattern in ASP.NET Core is the way to go. 在 ASP.NET Core 中使用选项模式是可行的方法。 I just want to add, if you need to access the options within your startup.cs , I recommend to do it this way:我只想补充一点,如果您需要访问 startup.cs 中的选项,我建议您这样做:

CosmosDbOptions.cs: CosmosDbOptions.cs:

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

Startup.cs:启动.cs:

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

I have gone throughconfiguration documentation on ASP.NET core.我已经阅读了有关 ASP.NET 核心的配置文档 Documentation says you can access configuration from anywhere in the application.文档说你可以从应用程序的任何地方访问配置。

Below is Startup.cs created by template下面是模板创建的 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();
    }
}

So in Startup.cs we configure all the settings, Startup.cs also has a property named Configuration所以在Startup.cs我们配置了所有的设置,Startup.cs还有一个名为Configuration的属性

What I'm not able to understand how do you access this configuration in controller or anywhere in the application?我无法理解您如何在控制器或应用程序中的任何地方访问此配置? MS is recommending to use options pattern but I have only 4-5 key-value pairs so I would like not to use options pattern. MS 建议使用选项模式,但我只有 4-5 个键值对,所以我不想使用选项模式。 I just wanted to have access to Configuration in application.我只是想访问应用程序中的配置。 How do I inject it in any class?我如何在任何课程中注入它?

I have to read own parameters by startup.我必须在启动时读取自己的参数。
That has to be there before the WebHost is started (as I need the “to listen” url/IP and port from the parameter file and apply it to the WebHost).它必须在 WebHost 启动之前就存在(因为我需要“监听”参数文件中的 url/IP 和端口并将其应用于 WebHost)。 Further, I need the settings public in the whole application.此外,我需要在整个应用程序中公开设置。

After searching for a while (no complete example found, only snippets) and after various try-and-error's, I have decided to do it the “old way" with an own.ini file.经过一段时间的搜索(没有找到完整的示例,只有片段)和各种尝试和错误之后,我决定使用 own.ini 文件以“旧方法”来做。
So.. if you want to use your own.ini file and/or set the "to listen url/IP" your own and/or need the settings public, this is for you...所以..如果你想使用你自己的.ini文件和/或设置你自己的“监听url/IP”和/或需要公开设置,这是给你的……

Complete example, valid for core 2.1 (mvc):完整示例,对核心 2.1 (mvc) 有效:

Create an.ini-file - example:创建 .ini 文件 - 例如:

[Startup] [启动]
URL= http://172.16.1.201:22222网址= http://172.16.1.201:22222
[Parameter] [范围]
*Dummy1=gew7623 *虚拟1=gew7623
Dummy1=true虚拟 1=真
Dummy2=1虚拟 2=1

whereby the Dummyx are only included as example for other date types than string (and also to test the case “wrong param” (see code below).其中 Dummyx 仅作为字符串以外的其他日期类型的示例包含在内(并且还用于测试“错误参数”的情况(请参见下面的代码)。

Added a code file in the root of the project, to store the global variables:在项目根目录添加代码文件,用于存放全局变量:

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

Changed the code in program.cs (before CreateWebHostBuilder()):更改了 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

    }
}

This way:这条路:

  • My Application config is separated from the appsettings.json and I have no sideeffects to fear, if MS does changes in future versions;-)我的应用程序配置与 appsettings.json 分开,如果 MS 在未来的版本中发生变化,我不必担心副作用;-)
  • I have my settings in global variables我在全局变量中有我的设置
  • I am able to set the "to listen url" for each device, the applicaton run's on (my dev machine, the intranet server and the internet server)我能够为每个设备设置“监听 url”,应用程序运行(我的开发机器、内联网服务器和互联网服务器)
  • I'm able to deactivate settings, the old way (just set a * before)我可以用旧方法停用设置(只需在之前设置一个 *)
  • I'm able to react, if something is wrong in the.ini file (eg type mismatch)如果 .ini 文件中有问题(例如类型不匹配),我能够做出反应
    If - eg - a wrong type is set (eg the *Dummy1=gew7623 is activated instead of the Dummy1=true) the host shows red information's on the console (including the exception) and I' able to react also in the application (GV.bFehler_Ini ist set to true, if there are errors with the.ini)如果 - 例如 - 设置了错误的类型(例如 *Dummy1=gew7623 被激活而不是 Dummy1=true)主机在控制台上显示红色信息(包括异常)并且我也能够在应用程序中做出反应(GV .bFehler_Ini ist 设置为 true,如果 .ini 有错误)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM