【问题标题】:ASP.NET Core web service does not load appsettings.json into configurationASP.NET Core Web 服务不会将 appsettings.json 加载到配置中
【发布时间】:2018-11-13 23:32:42
【问题描述】:

我有一个带有 Razor 页面的 ASP.NET Core 2.1 Web 应用程序,它在 appsettings.json 文件中定义了 AAD 身份验证信息(由默认应用程序模板提供 - 请参阅下文,了解我是如何到达那里的)。但是,当尝试在Startup.cs 中配置身份验证时,配置中没有我的appsettings.json 中的任何配置值。如果我在调试器中检查 IConfiguration 对象,那么它似乎只有环境变量配置:

这是问题所在的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 &gt; Add &gt; New Service Fabric Service 并选择了 Stateless ASP.NET Core [for .NET Framework],然后在下一页上我选择了 Web Application(带有 Razor Pages,而不是 MVC 的那个)并单击了 Change Authentication选择 Work or School Accounts 并输入我的 AAD 信息。我对此模板所做的唯一更改是在Startup.ConfigureServices 中的AddAzureAD 调用中添加代码,并将appsettings.json 文件设置为始终复制到输出目录。

为什么appsettings.json 文件没有加载到配置中?据我了解,这应该是默认发生的,但似乎缺少一些东西......

【问题讨论】:

  • WebHostBuilder默认不加载appsettings.json,需要手动调用AddJsonFile
  • 好吧,我会被诅咒的。果然,这解决了我的问题。我实际上并没有这样做,而是用WebHost.CreateDefaultBuilder() 替换了new WebHostBuilder(),但是为什么模板不能开箱即用是我无法理解的。谢谢!
  • 是的,这也会加载配置。我相信这是 2.0 的变化,也许你的模板是旧的?
  • 有可能。谁知道模板最后一次更新是什么时候,但它们显然没有经过非常彻底的测试

标签: c# asp.net asp.net-core


【解决方案1】:

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 来加载更多默认值。

【讨论】:

    【解决方案2】:

    另一种方法是通过ConfigurationBuilder 手动创建配置,然后使用UseConfiguration 方法。

    var configuration = new ConfigurationBuilder()
         .SetBasePath(Directory.GetCurrentDirectory())
         .AddJsonFile("appsettings.json", false, true)
         .Build();
    
    var host = new WebHostBuilder()
         .UseConfiguration(configuration)
         .UseKestrel()
         .UseStartup<Startup>();
    

    核心的主要目的是在实施时提供一点灵活性,他们经常错误地认为少即是多。你必须明确说出你想要什么,这样管道仍然相对较小。

    【讨论】:

      【解决方案3】:

      对于像我这样发现此问题的其他人:

      可能是您在构建期间没有复制 appsettings.json 文件。

      OP确实说他正在这样做,但这是一件小事 - 而这正是我没有做到的。

      你知道的越多……

      【讨论】:

        【解决方案4】:

        确保您的文件名全部小写。

        我的错误是将文件命名为 appSettings.json 而不是 appsettings.json。在 Linux 容器中运行时,驼峰式文件未加载。

        【讨论】:

          【解决方案5】:

          如前所述WebHostBuilder 不执行此默认行为CreateDefaultBuilder 需要改为调用。

          我更喜欢以下实现:

          public static void Main(string[] args)
          {
               var host = CreateHostBuilder(args).Build();
               var logger = host.Services.GetRequiredService<ILogger<Program>>();
          
               try
               {
                   logger.LogInformation("Starting up");
                          
                   host.Run();
                }
                catch (Exception ex)
                {
                   logger.LogCritical(ex, "Application start-up failed");
                }
          }
          
          public static IHostBuilder CreateHostBuilder(string[] args) =>
              Host.CreateDefaultBuilder(args)
                  .UseContentRoot(Directory.GetCurrentDirectory())
                  .ConfigureWebHostDefaults(webBuilder =>
                  {
                      webBuilder.UseStartup<Startup>();
                  });
          

          【讨论】:

            【解决方案6】:

            下面提到的步骤对我有用

            1. 转到 Appsettings.json
            2. 右键单击并转到属性
            3. 如果有内容,则从下拉菜单中选择构建操作为无
            4. 将副本复制到输出目录作为始终复制

            【讨论】:

              猜你喜欢
              • 2016-12-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-12-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多