在 ASP.NET Core 2 中的 webhost 之前开始记录

Start logging before webhost in ASP.NET Core 2

我想在 webhost 之前开始记录,所以记录了启动错误。所以我遵循 Serilog's recommended init order:1) 配置,2) 日志记录,3) webhost。我没有使用 CreateDefaultBuilder().

所以我的 Program.cs 有:

// setup config
var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
var configuration = new ConfigurationBuilder()
  .SetBasePath(Directory.GetCurrentDirectory())
  .AddJsonFile("appsettings.json", optional:false, reloadOnChange:true)
  .AddJsonFile($"appsettings.{envName}.json", optional:true, reloadOnChange:true)
  .AddEnvironmentVariables()
  .AddCommandLine(args)
  .Build();

// setup Serilog logging
Log.Logger = new LoggerConfiguration()
  .ReadFrom.Configuration(configuration)            // <<< uses config from above
  .CreateLogger()

// setup webhost
new WebHostBuilder()
  .UseConfiguration(configuration)                  // <<< uses config from above
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseStartup<Startup>()
  .UseSerilog()
  .Build()
  .Run();

这有效,但即使我指定了 reloadOnChange:true,也未检测到 appsettings.json 中的更改。

但是,当我使用 ConfigureAppConfiguration() 时,会检测到更改:

new WebHostBuilder()
  .ConfigureAppConfiguration((context, config) => {
    // .. duplicate config here
  })
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseStartup<Startup>()
  .UseSerilog()
  .Build()
  .Run();

但这意味着重复和可能无法预料的问题 - 即这是一个 hack。我该如何解决这个问题?

更新

根据@StephenZeng 的回答,UseConfiguration 在这里帮不了我,所以我想我需要使用 ConfigureAppConfiguration。但问题仍然存在 - 我如何先初始化我的配置,然后多次使用它而不重新定义它?

根据文档,它是设计使然:

"UseConfiguration only copies keys from the provided IConfiguration to the host builder configuration. Therefore, setting reloadOnChange: true for JSON, INI, and XML settings files has no effect."

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.1&tabs=aspnetcore2x

我 运行 遇到了同样的问题,我创建了一个负责配置生成器的方法。然后我从 Main 和构建 Web 主机时调用该方法。像这样:

public static class Program
{
  public static int Main()
  {
    var configuration = new ConfigurationBuilder()
      .AddConfiguration()
      .Build();

    // setup Serilog logging
    Log.Logger = new LoggerConfiguration()
      .ReadFrom.Configuration(configuration)
      .CreateLogger();

    // Code removed for brevity...
  }

  private static IWebHost BuildWebHost() =>
    WebHost.CreateDefaultBuilder()
      .UseSerilog()
      .UseStartup<Startup>()
      .ConfigureAppConfiguration((hostingContext, config) =>
      {
        // Clear default configuration
        config.Sources.Clear();

        // Replace with our own configuration
        config.AddConfiguration();
      })
      .Build();

  private static IConfigurationBuilder AddConfiguration(this IConfigurationBuilder self) =>
    self
      .SetBasePath(Directory.GetCurrentDirectory())
      .AddJsonFile("appsettings.json", optional:false, reloadOnChange:true)
      .AddJsonFile($"appsettings.{envName}.json", optional:true, reloadOnChange:true)
      .AddEnvironmentVariables();
}

解决方案是避免UseConfiguration并使用ConfigureAppConfiguration代替:

// setup config
// ..as before
// ..this is done only once

// setup Serilog logging
// ...as before

// setup webhost
new WebHostBuilder()
  .ConfigureAppConfiguration((context, config) => {
    config.AddConfiguration(configuration);  // <<< uses config from above
  })
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseStartup<Startup>()
  .UseSerilog()
  .Build()
  .Run();