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個のキーと値のペアの場合は、これらの個別の設定を挿入できます。テスト可能性のために、このアプローチまたはオプションパターンをお勧めします。(あなたが元々について尋ねたものを含む)すべての3つの方法が考えられる次の重複質問に答えとして記載されています: stackoverflow.com/questions/30263681/...
stephen.vakil

どこからでも辞書として構成にアクセスするには、この回答を確認してください
Amro 2017

完全なコード例については、こちらを確認してください。
Arghya C 2018

Framework構成をCORE構成に変換しているためにここに来た場合、この答えはstackoverflow.com/a/56498687/1704458
TS

回答:


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は常にnullです...コンストラクターでヒットすることはありません
dinotom

2
とは言っても、そのように通り過ぎるIConfigurationことは非常に漏れやすいです。オプションパターンを使用する方がはるかに優れています。
Marc L.

7
カスタムクラスで「appsettings.json」の値に直接アクセスする方法 コントローラからデータを渡すことなく?出来ますか?
Tadej

2
@HenkMollemaここに例を追加していただけませんか?どのようにして(どこから?)どのクラスに注入しますか?
Tadej

5
@HenkMollema問題は、どのクラスに注入するでした...「依存性注入によって解決されるクラス」に注入する方法ではありませんでした。私が誤解しているのはここだと思います...彼のクラスは、自動DIプロセスによって自動的に解決されるコントローラーまたは他のオブジェクトで始まるチェーンから呼び出されていない可能性があります。
BVernon 2018

34

それを行う正しい方法:

.NET CoreではIConfiguration、Classコンストラクターにパラメーターとしてを挿入できます。これを使用できます。

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

ここで、クラスのインスタンスを作成する場合、クラスにが注入されるため、コンストラクターに注入されるパラメーターが必要なため、IConfigurationだけでは実行できません。したがって、クラスを次のように注入する必要があります。インジェクションチェーンには、次の2つの簡単な手順が必要です。new MyClass()IConfiguration

あなたが使用したい- 1)あなたのクラス/ ESを追加IConfigurationし、IServiceCollectionConfigureServices()の方法で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。
アンドリュー、

1
もちろん問題は、コントローラだけでなく、あらゆるクラスの構成にアクセスすることでした。リーンサービス(マイクロサービス)の新しい開発では、これは考えられますが、移行に関しては、これは大きな問題です。これが、MicrosoftがSystem.ConfigurationCOREを軌道に戻した理由です。これで、古き良き時代と同じように、古き良きapp.configsにアクセスできます。そして、私はここでコントローラーについて話していません。独自の構成を持つコンポーネントについて話している
TS

コントローラーだけでなく、任意のクラスでのアクセスを許可します。依存性注入を得るためにコントローラーにインポートする必要があるだけです。
Mayer Spitzer

1
どちらの方法も有効であり、それぞれに対する賛成論または反対論は、私の意見では学術的なものです。私はさまざまなアプリケーションに両方を使用しました...今、非常に簡単な2番目のオプションのおかげで。静的クラスの作成は、DIを使用するとかなり困難です。
iGanja

2番目の方法は、.Net Core 2.0の一般的な問題にも役立ちます。POSTパラメーターとしてインスタンス化されたオブジェクト(つまり、JSONから自動的に逆シリアル化されます)で、コンストラクターに注入する機会がありません(少なくとも多くはありません)追加コードの)。これはそのシナリオに最適です
ジョームーン

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
あなたはNugetの依存関係を追加する必要があり@JedatKinports Microsoft.Extensions.ConfigurationMicrosoft.Extensions.Configuration.BinderそしてMicrosoft.Extensions.Configuration.Json、その後、あなたの負荷appsettings.jsonのようなファイル var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();..andをも、あなたが確認する必要がありappsettings.json、出力ディレクトリにコピーがに設定されているcopy always
LP13

7

またconfiguration、startup.csにstatic を作成するオプションがあるため、どこにでも簡単にアクセスでき、static変数は便利です。

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はデフォルトですでに注入に使用できると思います。
Pieter Heemeryck

はい、動作します。コメントを作成した後、これを試しました。構成の実装がIConfigurationに挿入されました。とにかくありがとう:)
ゴッドファーザー

1
@netfed Mayer Spitzerが彼の答えで述べているように、もちろんMyClassをスタートアップに追加して、必要な場所に注入する必要があるため、MyClassの新しいインスタンスを自分で作成する必要はなく、必要な場所に注入します。
Pieter Heemeryck

2

これを行うにはいくつかの方法がある可能性があることを知っています。Core3.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でも以前と同じように機能します。違いが1つあります。

Webアプリケーション([ASP.NET CORE WEB API] app.configなど)ではappSettingsまたはのweb.configではなく、使用する必要がありますconfigurationSection。を使用する必要があるかもしれませんが、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でアクセスする必要があるダースの構成値を持つサブセクション全体がある場合、それらすべてに対してそれを行う必要がありますか?IOptionsパターンを介してこれを行う他の方法はありませんか?大量輸送バスを構成する静的拡張メソッドにこれを注入する必要があります。また、ConfigureServicesdocs.microsoft.com /en
us/

ここではConfigureServiceでIOPtionsを使用しません...
Martin Brandl

-3

起動時に自分のパラメータを読み込まなければなりません。
これは、WebHostが起動する前に存在している必要があります(パラメーターファイルからURLとIPおよびポートを「リッスン」してWebHostに適用する必要があるため)。さらに、アプリケーション全体でパブリック設定が必要です。

しばらく検索した後(完全な例は見つからず、スニペットのみ)、さまざまな試行錯誤の後で、独自の.iniファイルを使用して「古い方法」を実行することにしました。
.iniファイルを所有するか、独自の「to listen 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が将来のバージョンで変更を行う場合、恐れる副作用はありません;-)
  • グローバル変数に設定があります
  • 各デバイスの "to listen url"を設定することができ、アプリケーションが実行されます(私の開発マシン、イントラネットサーバー、インターネットサーバー)。
  • 古い方法で設定を無効にできます(前に*を設定するだけです)
  • .iniファイルに問題がある
    場合(タイプの不一致など)、対応できます。例:間違ったタイプが設定されている(たとえば、Dummy1 = trueの代わりに* Dummy1 = gew7623がアクティブになっている)ホストが赤で表示される情報はコンソールにあり(例外を含む)、アプリケーションでも反応できます(.iniにエラーがある場合、GV.bFehler_Iniはtrueに設定されます)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.