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인스턴스를 서비스 컬렉션에 단일 객체 로 추가하는 것만 큼 쉽습니다 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는이 contstructor에 충격 결코 극복 ... 항상 널
dinotom

2
즉, 그렇게 지나가는 IConfiguration것은 매우 새는 것입니다. 옵션 패턴 을 사용하는 것이 훨씬 좋습니다 .
Marc L.

7
사용자 정의 클래스에서 직접 "appsettings.json"의 값에 액세스하는 방법은 무엇입니까? 컨트롤러에서 데이터를 전달하지 않고? 가능할까요?
Tadej

2
@HenkMollema 여기에 예제를 추가해 주시겠습니까? 클래스에 어떻게 주입 할 수 있습니까? (어디에서?)
Tadej

5
@HenkMollema 질문은 "종속성 주입을 통해 해결 된 모든 클래스"에 주입하는 방법이 아니라 모든 클래스 에 주입하는 방법이었습니다 . 나는 그것이 잘못된 의사 소통이있는 곳이라고 생각합니다 ... 그의 클래스는 자동 DI 프로세스에 의해 자동으로 해결되는 컨트롤러 또는 다른 객체로 시작하는 체인에서 호출되지 않을 가능성이 큽니다.
BVernon

34

이를 수행하는 올바른 방법 :

.NET Core에서는 IConfiguration클래스 생성자에 매개 변수로를 삽입 할 수 있으며 사용할 수 있습니다.

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

당신이 당신의 클래스가 주입됩니다 이후, 클래스의 인스턴스를 생성 할 때 지금 IConfiguration, 당신은 할 수 없습니다 new MyClass()그것이 필요하기 때문에, IConfiguration매개 변수는 생성자에 주입 그래서, 당신은 귀하의 클래스를 주입해야합니다, 주입 체인에 잘 맞습니다. 이는 두 가지 간단한 단계를 의미합니다.

당신은을 사용하려면 - 1) 클래스 / ES를 추가 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.
Andrew

1
물론 문제는 컨트롤러뿐만 아니라 모든 클래스의 구성에 액세스하는 것이 었습니다. 린 서비스 (마이크로 서비스)의 새로운 개발로 생각할 수 있지만 마이그레이션과 관련하여 이것은 큰 고통입니다. 이것이 Microsoft가 System.ConfigurationCORE를 다시 궤도에 올린 이유 입니다. 이제 예전처럼 좋은 예전 app.config에 액세스 할 수 있습니다. 그리고 저는 여기서 컨트롤러를 말하는 것이 아닙니다. 자체 구성이있는 구성 요소에 대해 이야기하고 있습니다
TS

컨트롤러뿐만 아니라 모든 클래스에서 액세스를 허용하며 종속성 주입을 얻기 위해 컨트롤러로 가져 오기만하면됩니다.
Mayer Spitzer

1
두 가지 방법 모두 효과가 있으며 각각에 대한 논쟁은 학문적입니다. 매우 쉬운 두 번째 옵션 덕분에 다른 응용 프로그램에 두 가지를 모두 사용했습니다. DI를 사용하여 정적 클래스를 만드는 것은 다소 어렵습니다.
iGanja

두 번째 방법은 .Net Core 2.0의 일반적인 문제를 해결하는 데 도움이됩니다. POST 매개 변수로 인스턴스화 된 객체 (즉, JSON에서 자동으로 직렬화 해제 됨), 생성자에 주입 할 기회가 없습니다 (적어도 많은 추가 코드). 이 시나리오에서 잘 작동합니다
Joe Moon

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"의 값에 액세스하는 방법은 무엇입니까?
Tadej

2
당신이 필요 @JedatKinports는 Nuget 종속성을 추가 Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.BinderMicrosoft.Extensions.Configuration.Json다음로드 appsettings.json같은 파일을 var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();.. 그리고 또한 당신이 있는지 확인해야 appsettings.json으로 설정되어 출력 디렉토리에 복사copy always
LP13

7

나는 지금 이렇게하고있다.

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

마지막으로 인젝터 광기에 의존하지 않고 정적 메서드로 작동하는 것. 마침내 역설적 독립! ;-) ...하지만 NuGet 패키지 종속성이 너무 많습니다!
Louis Somers

7

또한 configurationstartup.cs에 정적 으로 만들 수있는 옵션이있어서 어디서든 쉽게 액세스 할 수 있습니다. 정적 변수는 편리합니다.

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

internal static IConfiguration Configuration { get; private set; }

이렇게하면 Startup.Configuration.GetSection...What can go wrong?을 사용하여 어디서나 구성에 액세스 할 수 있습니다.


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은 기본적으로 이미 주입 할 수 있다고 생각합니다.
Pieter Heemeryck

예, 작동합니다. 주석을 작성하고 구성 구현이 IConfiguration에 주입 된 후 이것을 시도했습니다. 어쨌든 감사합니다 :)
The Godfather

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 월 Microsoft는 System.Configuration.NET CORE v4.4 용으로 출시되었습니다 . 현재 v4.5 및 v4.6 미리보기.

.Net Framework에서 CORE 로의 전환을 작업하는 우리에게는 이것이 필수적입니다. app.config모든 어셈블리에서 액세스 할 수있는 현재 파일 을 유지하고 사용할 수 있습니다. appsettings.jsonMicrosoft가 그 필요성을 인식했기 때문에 아마도 . FW에서 이전과 동일하게 작동합니다. 한 가지 차이점이 있습니다.

웹 애플리케이션에서, [예를 들어, ASP.NET 핵심 웹 API] 당신은 사용해야 app.config하고 하지 당신을위한의 Web.config appSettingsconfigurationSection. web.configIIS를 통해 사이트를 배포하는 경우에만 사용해야 할 수도 있습니다 . 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에서 액세스해야하는 12 개의 구성 값이있는 전체 하위 섹션이 있으면 모두에 대해 수행해야합니까? IOptions 패턴을 통해이 작업을 수행하는 다른 방법이 없습니까? 대중 교통 버스를 구성하는 정적 확장 방법에 이것을 삽입해야합니다. 또한 ConfigureServices docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/…
kuldeep

여기 ConfigureService에서 IOPtions를 사용하지 않습니다 ...
Martin Brandl

-3

시작시 자체 매개 변수를 읽어야합니다. 웹 호스트가 시작 되기 전에
거기에 있어야합니다 (매개 변수 파일에서 "수신 할"url / IP 및 포트가 필요하므로 웹 호스트에 적용합니다). 또한 전체 응용 프로그램에서 공개 설정이 필요합니다 .

한동안 검색 한 후 (완전한 예제가 발견되지 않고 스 니펫 만) 다양한 시도와 오류를 겪은 후 고유 한 .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가 향후 버전에서 변경하면 두려워 할 부작용이 없습니다 ;-)
  • 전역 변수에 내 설정이 있습니다.
  • 각 장치에 대한 "수신 URL"을 설정할 수 있으며 응용 프로그램이 실행됩니다 (내 개발 컴퓨터, 인트라넷 서버 및 인터넷 서버).
  • 이전 방식으로 설정을 비활성화 할 수 있습니다 (이전에 * 만 설정)
  • .ini 파일에 문제가있는
    경우 (예 : 유형 불일치) 대응할 수 있습니다. 예를 들어 잘못된 유형이 설정된 경우 (예 : Dummy1 = true 대신 * Dummy1 = gew7623이 활성화 됨) 호스트가 빨간색으로 표시됩니다. 정보는 콘솔 (예외 포함)에 있고 응용 프로그램에서도 반응 할 수 있습니다 (.ini에 오류가있는 경우 GV.bFehler_Ini가 true로 설정되지 않음)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.