web-dev-qa-db-ja.com

ASP.net Core 2.0 Preview構成のappsettings.json GetSection null

Startup.csに挿入された構成からGetSectionを呼び出そうとしました。値はnullでしたが、具体的なセクション値へのindexernon-null値を返します。 GetSectionメソッドの背後にあるバグのように見えますか、それとも間違っていますか?

appsettings.json:

{"MyConfig":{"ConfigA": "valueA"、 "ConfigB": "valueB"}}

Program.cs:

    public static void Main(string[] args)
    {
        var Host = BuildWebHost(args);
        Host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();

Startup.cs:

public class Startup
{
    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.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var mySection = this.Configuration.GetSection("MyConfig");

        var myVal = this.Configuration["MyConfig:ConfigA"];
14
rychlmoj

最初に、JSONファイルから取得可能な値を構築する内部コードであるJsonConfigurationProvider.cs1.1.12.x の間に変更があるかどうかを確認しました。これや、最終的にthis.Configuration.GetSection("MyConfig");によって呼び出される他のコードに変更はありませんでした。

値を取得する方法は、Configurationが各構成プロバイダーでキーMyConfigを逆順で検索することです。値が見つかるまでコードで定義されているとおり。あなたの例では、プロバイダー(json、環境変数、コマンドライン引数)はWebhost.CreateDefaultBuilder()(こちらを参照) で提供されています。

JsonConfigurationFileParser.cs のコードを見ると、キーと値のDictionary<string, string>が作成されますただし、プリミティブ値のみ。つまり、MyConfig(このレベルではオブジェクト)のキーは保存されませんが、MyConfig:ConfigAのキーがあり、配列値はMyConfig:ConfigA:0MyConfig:ConfigA:1などのようになります。

最後に、Configuration.GetSection("MyConfig")常に新しく構築されたものを返しますConfigurationSectionつまりnever null、最悪の場合はValueproperty of nullになります。

したがって、IntellisenseでConfigurationSectionにカーソルを合わせてValueプロパティを見ると、every構成プロバイダーが検索され、キーを持つものが見つからなかったことがどうなりますか返される文字列に変換されたプリミティブ値を持つ「MyConfig」の。

少なくとも以下を呼び出す必要があります。

services.Configure<MyConfigOptions>(configuration.GetSection("MyConfig"));
services.AddSingleton(cfg => cfg.GetService<IOptions<MyConfigOptions>>().Value);

アプリ全体にC#オブジェクトとして注入します。そうでない場合は、コロン["MyConfig:ConfigA"]セパレーター構文またはvar mySection = this.Configuration.GetSection("MyConfig")["ConfigA"];を使用して個々の値を呼び出します。これは冗長ですが、プリミティブの取得にのみ使用されることを示しています。

C#オブジェクトにバインドして注入するために、次の拡張メソッドを作成しました。

public static class IServiceCollectionExtensions
{
    public static IServiceCollection AddConfigOptions<TOptions>(this IServiceCollection services,
        IConfiguration configuration, string section) where TOptions : class, new()
    {
        services.Configure<TOptions>(configuration.GetSection(section));
        services.AddSingleton(cfg => cfg.GetService<IOptions<TOptions>>().Value);
        return services;
    }
}

次のように呼び出すことができます。

public class Startup
{
    public Startup(IConfiguration configuration) => Configuration = configuration;

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddConfigOptions<EmailOptions>(Configuration, "Email")

そして次のように注入されます:

public class EmailSender : IEmailSender
{
    private EmailOptions _emailOptions;

    public EmailSender(EmailOptions options) => _emailOptions = options;
12

私の場合、パッケージがありませんでした:

Microsoft.Extensions.Configuration.Binder

実際には、 here の微妙なコードコメントとして文書化されています

1
Bruno Garcia

AspNetCore 2.0は、構成の点で1.xよりもはるかに単純であることがわかりました。

Startup(IConfiguration configuration)コンストラクターにブレークポイントを配置すると、configuration変数には約5つのプロバイダーが含まれることに気付くでしょう。

JsonConfigurationProviderは、appsettings.jsonファイルで関心のあるプロバイダーですが、おそらくDataプロパティには_Count=0_。これはおそらく、アプリケーションが_JsonConfigurationProvider.Source.FileProvider.Root_(デフォルトではwwwroot)で指定されたディレクトリでappsettings.jsonファイルを探しているという事実によるものです。

次のように、.csprojファイルにMSBuildタスクを追加しました。

_<Copy SourceFiles="appsettings.json" DestinationFolder="wwwroot" />
_

そして、それは完璧に機能するように見えました。

これは明らかにローカル開発のみ中に役立ちます。ただし、最近の一般的なプラクティスでは、最初にファイルに構成を設定することはありません。特に、リポジトリの履歴の一部になるためです。代わりに、アプリをデプロイするとき、最近の2つの一般的なプラクティスは、環境変数を使用して値をオーバーライドするか、consulなどのキー/値ストアを使用することです。

さらに、services.Configure<>()を使用する方法についての素晴らしい例がオンラインでたくさんありますが、_Startup.cs_は既にDIを使用して_IConfiguration configuration_に値を注入します。これは、IConfigurationが.NETコアのIoCコンテナーに既に登録されていることを意味します。したがって、本質的には、アプリの他のクラスでIConfigurationを次のように使用できることを意味します。

_public JobsRepository(IConfiguration configuration)
{
    this.configA = configuration.GetSection("MyConfig:ConfigA").Value;
}
_
0
Adel Helal