如何在ASP.NET Core中的任何类中访问Configuration?


127

我已经阅读了ASP.NET Core上的配置文档。文档说您可以从应用程序中的任何位置访问配置。

以下是模板创建的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

如果您是因为将框架配置转换为CORE配置而来这里的,那么此答案将为您提供stackoverflow.com/a/56498687/1704458
TS

Answers:


147

更新资料

使用ASP.NET Core 2.0会将应用程序的实例自动添加IConfiguration到依赖项注入容器中。这也适用于连同ConfigureAppConfigurationWebHostBuilder

例如:

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

4
Mollerna ....以及是否要将配置注入解决方案中单独的类库项目中呢?像这样尝试私有静态IConfiguration _configuration {get; 组; } public DatabaseHelpers(IConfiguration configuration){_configuration = configuration; },但_configuration始终为空...它永远不会在构造函数中被击中
dinotom

2
就是说,IConfiguration像这样的路过很漏水。使用Options模式要好得多。
Marc L.

7
如何直接在自定义类中从“ appsettings.json”访问值?没有传递来自控制器的数据?可能吗?
塔德伊

2
@HenkMollema您可以在这里添加示例吗?我如何将其注入任何班级(从哪里来?)。
塔德吉

5
@HenkMollema问题是如何注入到任何类中,而不是如何注入到“通过依赖注入解决的任何类中”。我认为那是沟通不畅的地方...可能不会从以Controller或通过自动DI流程自动解决的其他对象开始的链中调用他的类。
BVernon

34

正确的方法:

在.NET Core中,您可以将IConfigurationas作为参数注入到您的Class构造函数中,它将可用。

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

现在,当您要创建类的实例时,由于您的类被注入IConfiguration,您将无法执行操作new MyClass(),因为它需要将一个IConfiguration参数注入构造函数中,因此,您需要将类注入为对注入链而言,这意味着两个简单的步骤:

1)将您的Classes添加IConfigurationIServiceCollection中的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为静态配置类的想法。
Andrew

1
当然,问题是关于访问任何类中的配置,而不仅仅是控制器。而且随着精益服务(微服务)的新发展,可以想到的是,在迁移方面,这是一个很大的痛苦。这就是Microsoft System.Configuration使CORE回到正轨的原因。现在,您可以像过去一样访问旧的app.configs。我在这里不是在谈论控制器。我们正在谈论具有自己配置的组件
TS

它允许在任何类中访问,而不仅仅是在控制器中,它只需要导入到控制器中即可获得依赖注入。
Mayer Spitzer

1
无论哪种方法都能奏效,我认为支持或反对每种方法的论点都是学术性的。由于您极为简单的第二种选择,我已经将这两种方法用于不同的应用程序...现在。使用DI创建静态类非常困难。
iGanja

第二种方法也有助于解决.Net Core 2.0中的一个常见问题-将对象实例化为POST参数(即,从JSON自动反序列化),在这种情况下您没有机会注入到构造函数中(至少不是很多)额外的代码)。这对于这种情况非常有用
Joe Moon

30

我知道这很老,但是鉴于IOptions模式实现起来相对简单:

  1. 具有与配置中的设置相匹配的公共获​​取/设置属性的类

    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.ConfigurationMicrosoft.Extensions.Configuration.BinderMicrosoft.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
}

它可以在没有类似Startup.cs的情况下明确提及MyClass吗?services.AddTransient <MyClass>();
教父

是的,实际上,您应该在Startup.cs中提到要注入的类,而不是相反。但是我认为IConfiguration在默认情况下已经可以注入。
彼得·海默里克

是的,它有效。我在添加注释并将config实现注入IConfiguration后尝试了此操作。无论如何还是要谢谢:)
教父

1
@netfed正如Mayer Spitzer在他的回答中指出的那样,您当然需要将MyClass添加到启动中,然后将其注入到您需要的任何位置,因此您无需自己创建MyClass的新实例,而是在需要的地方注入它。
Pieter Heemeryck,

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控制器,因此首先添加了using引用,然后注入了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

在2017年8月8日,Microsoft推出System.Configuration了.NET CORE v4.4 版本。当前v4.5和v4.6预览。

对于那些致力于从.Net Framework到CORE转换的人们来说,这是至关重要的。它允许保留和使用当前app.config文件,可以从任何程序集访问该文件。appsettings.json由于Microsoft意识到了它的必要性,因此它甚至可以替代。与以前的固件相同。有一个区别:

在Web应用程序,[如ASP.NET核心Web API]你需要使用app.config没有为你的web.config appSettingsconfigurationSection。您可能需要使用,web.config但仅当您通过IIS部署站点时才需要使用。您将特定于IIS的设置放入web.config

我已经用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关于不使用ConfigureServices docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/中的
kuldeep

我不在这里的ConfigureService中使用IOPtions ...
Martin Brandl

-3

我必须在启动时读取自己的参数。启动WebHost 之前
,必须存在该位置(因为我需要“侦听”参数文件中的url / IP和端口并将其应用于WebHost)。此外,我需要在整个应用程序中公开设置。

搜索了一会儿(不完整的示例中,仅段),并经过多方尝试和错误的,我已经决定这样做了“老办法”用自己的.ini文件。之后
所以..如果你想用你的拥有.ini文件和/或自行设置“侦听url / IP”和/或需要公共设置,这是给您的...

完整示例,对核心2.1(mvc)有效:

创建一个.ini文件-示例:

[启动]
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在将来的版本中进行了更改,我也没有担心的副作用;-)
  • 我在全局变量中有设置
  • 我能够为每台设备(运行我的开发机,Intranet服务器和Internet服务器)上的applicaton设置“侦听url”
  • 我可以停用设置的旧方法(只需在之前设置*)
  • 我可以做出反应,如果.ini文件中有问题(例如类型不匹配),
    如果-例如-设置了错误的类型(例如* Dummy1 = gew7623被激活,而不是Dummy1 = true),则主机显示红色信息在控制台上(包括异常),并且我也可以在应用程序中做出反应(如果.ini错误,则将GV.bFehler_Ini ist设置为true)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.