【问题标题】:Starting ASP.NET Core from Visual Studio doesn't start from build folder从 Visual Studio 启动 ASP.NET Core 不是从构建文件夹开始
【发布时间】:2019-11-15 05:35:25
【问题描述】:

当您从 Visual Studio (2017) 启动 ASP.NET Core 项目时,它假定工作目录是源代码所在的位置,而不是构建文件的实际放置位置。

这意味着当我运行我的项目时,它会从C:\Path\To\My\Project\appsettings.json 读取配置文件,而不是从C:\Path\To\My\Project\bin\Debug\appsettings.json

我在调试这段代码的时候可以看到是这样的:

WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureAppConfiguration((context, config) => {
        config.SetBasePath(context.HostingEnvironment.ContentRootPath);
        config.AddJsonFile("appsettings.json", true, false);
    });

ContentRootPath 指向项目文件夹的位置,而不是构建文件所在的位置。

我可以通过在Project Properties &gt; Debug 中设置Working Directory 来解决这个问题,但是由于我们也在使用配置转换(SlowCheetah),每个开发人员都将拥有自己的调试输出构建配置(bin\Debug[CustomConfiguration]),并为一位开发人员更改 .csproj 会破坏所有其他开发人员。

有没有什么方法可以让 ASP.NET Core 从放置构建文件的位置而不是项目文件夹中读取配置文件,而无需更改 Working Directory,但仍然适用于多个“构建配置”?

【问题讨论】:

  • 微软就是这样设计的,blog.lextudio.com/…
  • @LexLi 是的,很明显。如何规避这个问题以便使用 SlowCheetah 变换?
  • 让SlowCheetah 开发人员更改他们的代码以适应这样的设计。

标签: c# asp.net-core visual-studio-2017 appsettings slowcheetah


【解决方案1】:

如果我正确理解了这个问题,那么每个开发人员的用户名都有不同的输出文件夹。所以,如果你编造这样的东西,

        var debug = string.Empty;
        #if DEBUG
            debug = "Debug";
        #else
            debug = "Release";
        #endif

        var userNameVariable = System.Environment.GetEnvironmentVariable("USER");
        debug += $"[{userNameVariable}]";

        var path = System.IO.Path.Combine(env.ContentRootPath, "bin", debug);
        var builder = new ConfigurationBuilder()
            .SetBasePath(path) //env.ContentRootPath
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();

我已经在 Mac OS 上测试过,结果是

/Users/johndoe/Documents/Temp/contentasp/bin/Debug[johndoe]

其他解决方案。

在 Visual Studio 中,您有预构建和构建后脚本。在 Visual Studio 中,您可以获取 OutputFolder 并将路径设置为预构建脚本上的环境变量。例如:

powershell.exe -ExecutionPolicy Bypass -File "$(ProjectDir)outputscript.ps1" -OutputFolder $(OutputPath)

并且在 powershell 脚本中 (outputscript.ps1)

Param(
    [Parameter(Mandatory = $true, Position = 1)]
        [string]$OutputFolder
)

$env:OutputFolder = $OutputFolder

你可以在启动时获得价值

var outputFolder = System.Environment.GetEnvironmentVariable("OutputFolder");
var builder = new ConfigurationBuilder()
    .SetBasePath(outputFolder) //env.ContentRootPath

【讨论】:

  • 没有真正的用户名,只是使用命名标准的不同构建配置:Debug[initials of user],因此为开发环境创建所有代码似乎有点过分
  • 另一种解决方案是,如果您可以在预构建脚本上将输出文件夹路径设置为环境变量。您可以从System.Environment.GetEnvironmentVariable("OutputFolder") 获取它并设置到 SetBasePath。我认为不存在对此的本地解决方案,您必须即兴发挥。
【解决方案2】:

也许这将有助于通过以下方式将目录设置为应用程序工作目录:

Directory.SetCurrentDirectory(context.HostingEnvironment.ContentRootPath);

【讨论】:

  • context.HostingEnvironment.ContentRootPath 指向C:\Path\To\My\Project,而我想从C:\Path\To\My\Project\bin\debug[User] 运行(因为这是放置转换后的appsettings.json 文件的位置)
  • 设置复制到 .csproj 中的 bin 目录?
  • appsettings.json 已复制到bin 目录。问题是在Visual Studio中做Debug &gt; Start Debugging时,不是从bin目录开始,而是从项目目录开始,所以找不到转换后的文件。
【解决方案3】:

从您通过SetBasePath 配置的位置读取配置文件。在开发模式下发生的情况是,当您使用 WebHost.CreateDefaultBuilder 时,它会将 BasePath 设置为源代码文件夹,这对于大多数开发人员案例来说都是合乎逻辑的。

它实际上不适用于控制台应用程序,例如,所以我专门在那里做同样的事情。

可能有几种方法可以解决此问题:

  1. 默认使用现有系统非常方便。也许您可以更详细地解释为什么它不适合您?

  2. 不使用CreateDefaultBuilder 并自己创建构建器,那么您将能够完全按照您的需要进行配置。

  3. 用你想要的值覆盖SetBasePath。我假设例如AppContext.BaseDirectoryDirectory.GetCurrentDirectory() 将返回您正在寻找的路径

  4. 不为您的环境使用名称“开发”可能也可以解决问题,但您需要考虑一些其他后果。

附:当您可以使用敏捷配置时,您为什么还要使用 slowcheetah 进行旧式转换?您可以从多个文件中读取配置,最后一个文件的顺序总是获胜,因此它与在实践中使用 slowcheetah 的效果相同。

【讨论】:

    猜你喜欢
    • 2017-08-20
    • 2021-05-08
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 2018-04-13
    • 2016-11-23
    • 1970-01-01
    • 2021-11-15
    相关资源
    最近更新 更多