web-dev-qa-db-ja.com

ASP.NET Core Webサービスはappsettings.jsonを構成にロードしません

appsettings.jsonファイルで定義されたAAD認証情報を持つRazor Pagesを備えたASP.NET Core 2.1 Webアプリケーションがあります(デフォルトのアプリケーションテンプレートのおかげです。その方法については以下を参照してください)。ただし、Startup.csで認証を構成しようとすると、構成にはappsettings.jsonの構成値が含まれません。デバッガーでIConfigurationオブジェクトを調べると、環境変数の構成のみがあるように見えます。

enter image description here

問題があるStartup.ConfigureServicesメソッドは次のとおりです。

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
        .AddAzureAD(options =>
        {
            // This is from the default template. It should work, but the relevant settings aren't there so options isn't populated.
            this.Configuration.Bind("AzureAd", options);

            // This of course works fine
            options.Instance = "MyInstance";
            options.Domain = "MyDomain";
            options.TenantId = "MyTenantId";
            options.ClientId = "MyClientId";
            options.CallbackPath = "MyCallbackPath";
        });

    services.AddMvc(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

また、重要な場合のサービス構成(これは、サービスファブリックステートレスサービスの上に構築されていることに注意してください):

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                return new WebHostBuilder()
                            .UseKestrel(opt =>
                            {
                                int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
                                opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
                                {
                                    listenOptions.UseHttps(GetCertificateFromStore());
                                    listenOptions.NoDelay = true;
                                });
                            })
                            .ConfigureServices(
                                services => services
                                    .AddSingleton<StatelessServiceContext>(serviceContext))
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseStartup<Startup>()
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url)
                            .Build();
            }))
    };
}

このサービスを作成するには、VS2017のウィザードを使用しました。既存のサービスファブリックプロジェクト(.sfproj)を選択し、Services > Add > New Service Fabric Serviceを選択し、Stateless ASP.NET Core [for .NET Framework]を選択した後、次のページでWeb Application(MVCではなくRazor Pagesを使用するもの)を選択しました)[Change Authentication]をクリックし、Work or School Accountsを選択してAAD情報を入力しました。このテンプレートに加えた唯一の変更は、Startup.ConfigureServicesAddAzureADへの呼び出し内にコードを追加し、appsettings.jsonファイルを常に出力ディレクトリにコピーするように設定することです。

appsettings.jsonファイルが構成に読み込まれないのはなぜですか?理解しているように、これはデフォルトで発生するはずですが、何かが欠落しているようです...

11
wlyles

WebHostBuilderは読み込まれませんappsettings.jsonデフォルトでは、AddJsonFileを手動で呼び出す必要があります。例えば:

return new WebHostBuilder()
            .UseKestrel(opt =>
            {
                //snip
            })
            .ConfigureAppConfiguration((builderContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: false);
            })
            .ConfigureServices(
                services => services
                    .AddSingleton<StatelessServiceContext>(serviceContext))
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
            .UseUrls(url)
            .Build();

または、 WebHost.CreateDefaultBuilder より多くのデフォルトをロードします。

11
DavidG

別のアプローチは、ConfigurationBuilderを介して手動で構成を作成し、UseConfigurationメソッドを使用することです。

var configuration = new ConfigurationBuilder()
     .SetBasePath(Directory.GetCurrentDirectory())
     .AddJsonFile("appsettings.json", false, true)
     .Build();

var Host = new WebHostBuilder()
     .UseConfiguration(configuration)
     .UseKestrel()
     .UseStartup<Startup>();

主要な目的は、実装時に多少の柔軟性を提供するためのコアであり、多くの場合、エラーが少ないほど多くなります。パイプラインが比較的小さいままであるように、あなたが望むものを明示的に言わなければなりません。

2
Greg