如何设置环境名称(IHostingEnvironment.EnvironmentName)?

How to set Environment Name (IHostingEnvironment.EnvironmentName)?

默认 ASP.NET 核心 Web 项目在 Startup.cs 中包含这样的行:

if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
    app.UseBrowserLink();
    app.UseDeveloperExceptionPage(ErrorPageOptions.ShowAll);
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

据我了解,EnvironmentName 是一种处理 Dev/Production 环境的新方法。但它不会改变发布构建配置。那么设置不同的EnvironmentName有什么方法呢?

我可以想象它应该设置在"Commands"作为服务器的参数。

您通过定义一个名为 ASPNET_ENV 的环境变量来设置环境。 例如,如果您想要发布 SET ASPNET_ENV=Release.

如果您将 ASPNET_ENV=Release 作为参数传递给命令,它也可能会起作用,但我现在无法检查它。

实现方式如下:https://github.com/aspnet/Hosting/blob/217f9ca3d3ccf59ea06e6555820974ba9c3b5932/src/Microsoft.AspNet.Hosting/ConfigureHostingEnvironment.cs

如果您认为它从哪里获取这个值,那么此时它是静态的,默认值为开发。

https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/HostingEnvironment.cs

当您查看 IHostingEnviroment 变量类型时,它是 Microsoft.AspNet.Hosting.HostingEnvrioment。

您现在可以通过两种方式根据动态配置进行更改。

  1. 您可以实现 IHostingEnvironment 接口并为此使用您自己的类型。您可以从配置文件中读取值。

  2. 您可以使用接口您可以直接在此处更新该变量。

    public Startup(IHostingEnvironment env)
    {
    // Setup configuration sources.
    Configuration = new Configuration()
        .AddJsonFile("config.json").AddEnvironmentVariables();
    
    Configuration.Set("ASPNET_ENV","Your own value");    
    }
    

    如果您查看 ConfigureServices 中的服务,会发现默认配置的服务列表,其中之一是 IConfigureHostingEnviroment。默认实现是内部 class 所以你不能直接访问但是你可以设置上面的键 ASPNET_ENV 并且它读取那个值。

https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/ConfigureHostingEnvironment.cs

RC2之后

So what is the way to set a different EnvironmentName?

设置ASPNETCORE_ENVIRONMENT环境变量。

设置该环境变量的方法有很多种。其中包括 launchSettings.json 个人资料和 other environment-specific ways。这里有一些例子。

从控制台:

// PowerShell
> $env:ASPNETCORE_ENVIRONMENT="Development"

// Windows Command Line
> SET ASPNETCORE_ENVIRONMENT=Development

// Bash
> ASPNETCORE_ENVIRONMENT=Development

来自 Azure Web 应用程序的应用程序设置:

RC2 之前

I can imagine that it should be set in "Commands" as a parameter for server.

没错。在您的 project.json 中,添加 --ASPNET_ENV production 作为服务器的参数。

"commands": {
  "web": "Microsoft.AspNet.Hosting --ASPNET_ENV production --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5001"
}

现在,当您从命令行 运行 dnx . web 时,ASPNET_ENV 将是 production

相关ASP.NET核心托管源代码

WebHostBuilder"ASPNETCORE_"WebHostDefaults.EnvironmentKey 合并为 "ASPNETCORE_environment"。它还支持旧密钥。

WebHostDefaults.cs

namespace Microsoft.AspNetCore.Hosting
{
    public static class WebHostDefaults
    {
        public static readonly string ApplicationKey = "applicationName";
        public static readonly string StartupAssemblyKey = "startupAssembly";

        public static readonly string DetailedErrorsKey = "detailedErrors";
        public static readonly string EnvironmentKey = "environment";
        public static readonly string WebRootKey = "webroot";
        public static readonly string CaptureStartupErrorsKey = "captureStartupErrors";
        public static readonly string ServerUrlsKey = "urls";
        public static readonly string ContentRootKey = "contentRoot";
    }
}

WebHostBuilder.cs

_config = new ConfigurationBuilder()
    .AddEnvironmentVariables(prefix: "ASPNETCORE_")
    .Build();

if (string.IsNullOrEmpty(GetSetting(WebHostDefaults.EnvironmentKey)))
{
    // Try adding legacy environment keys, never remove these.
    UseSetting(WebHostDefaults.EnvironmentKey, 
        Environment.GetEnvironmentVariable("Hosting:Environment") 
        ?? Environment.GetEnvironmentVariable("ASPNET_ENV"));
}

向后兼容性

The environment key is set with the ASPNETCORE_ENVIRONMENT environment variable. ASPNET_ENV and Hosting:Environment are still supported, but generate a deprecated message warning.

https://docs.asp.net/en/latest/migration/rc1-to-rtm.html

默认值

默认值为"Production"and is set here.

  1. 在 Azure 上只需在 Web 应用程序配置页面上设置 ASPNET_ENV 环境变量。

  2. 使用您自己的 IIS 或其他托管服务提供商 - 修改 web.config 以包含 "web" 命令的参数:

    <configuration>
     <system.webServer>
      <handlers>
        <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
      </handlers>
      <httpPlatform processPath="..\approot\web.cmd" arguments="--ASPNET_ENV Development" stdoutLogEnabled="false" stdoutLogFile="..\logs\stdout.log" startupTimeLimit="3600"></httpPlatform>
     </system.webServer>
    </configuration>
    
  3. 在开发过程中(如果你可以修改源代码),你也可以在项目的根目录下创建名为Microsoft.AspNet.Hosting.json的文件并设置ASPNET_ENV 变量。

    { "ASPNET_ENV": "Test" }

如果您需要在不更改代码的情况下进行设置 - 从项目源文件夹根目录下的命令提示符类型:

set ASPNET_ENV=Debug

ASP.NET Core RC2 中,变量名称已更改为 ASPNETCORE_ENVIRONMENT

例如在 Windows 中,您可以在登台服务器上执行此命令(具有管理员权限)

SETX ASPNETCORE_ENVIRONMENT "Staging" /M

这只会被执行一次,之后,服务器将始终被视为暂存服务器。

当您在该服务器的命令提示符中执行 dotnet run 时,您将看到 Hosting environment: Staging

launchsettings.json

在属性 > launchsettings.json

就像这样:

    {
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:1032/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    },
    "WebAppNetCore": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "web": {
      "commandName": "web",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

VsCode中将以下内容添加到launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            ...
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            }
        },
        ...
    ]
}

我有同样的问题。为了独立于环境变量和 web.config,我创建了一个 .json 文件(我称之为 envsettings.json):

{
  // Possible string values reported below.
  // - Production
  // - Staging
  // - Development
  "ASPNETCORE_ENVIRONMENT": "Staging"
}

然后在 Program.cs 我添加了:

public class Program
{
    public static void Main(string[] args)
    {
        var currentDirectoryPath = Directory.GetCurrentDirectory();
        var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
        var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
        var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();

        var webHostBuilder = new WebHostBuilder()
            .UseKestrel()
            .CaptureStartupErrors(true)
            .UseSetting("detailedErrors", "true")
            .UseContentRoot(currentDirectoryPath)
            .UseIISIntegration()
            .UseStartup<Startup>();

        // If none is set it use Operative System hosting enviroment
        if (!string.IsNullOrWhiteSpace(enviromentValue)) 
        {
            webHostBuilder.UseEnvironment(enviromentValue);
        }

        var host = webHostBuilder.Build();

        host.Run();
    }
}

如果您更喜欢使用 VS 功能(例如 VS 2017),可以在项目属性的调试选项卡中添加环境变量。例如,在最新的 ASP.NET 核心版本(RC2 之后)上,您应该设置 ASPNETCORE_ENVIRONMENT 变量。

因此,launchSettings.json 文件将在相应项目的 Properties 文件夹中创建(或更新),因此很容易持久化此文件进入您的源代码管理解决方案并在开发人员之间共享(与使用 SET / SETX 命令的其他解决方案相反)

注意:默认情况下,最新的 ASP.NET Core 将环境设置为 Production。因此,您只需要在 VS 中将 ASPNETCORE_ENVIRONMENT 设置为 Development 以进行调试(参见上面的屏幕截图)。当然,当你想 运行 你的代码在本地使用暂存环境时,你应该将 ASPNETCORE_ENVIRONMENT 设置为 Staging。最后,当您想在生产环境中 运行 它时,只需删除此变量或将值设置为 Production.

总结一下:只需确保使用 DevelopmentStagingProduction 值(不是 'Dev' 或其他任何东西)在调试对话框中设置环境并使不同的扩展工作。

另请参阅 ASP.NET 核心的相关源代码:

namespace Microsoft.AspNetCore.Hosting
{
  /// <summary>Commonly used environment names.</summary>
  public static class EnvironmentName
  {
    public static readonly string Development = "Development";
    public static readonly string Staging = "Staging";
    public static readonly string Production = "Production";
  }
}

namespace Microsoft.AspNetCore.Hosting
{
  /// <summary>
  /// Extension methods for <see cref="T:Microsoft.AspNetCore.Hosting.IHostingEnvironment" />.
  /// </summary>
  public static class HostingEnvironmentExtensions
  {
    /// <summary>
    /// Checks if the current hosting environment name is "Development".
    /// </summary>
    /// <param name="hostingEnvironment">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.IHostingEnvironment" />.</param>
    /// <returns>True if the environment name is "Development", otherwise false.</returns>
    public static bool IsDevelopment(this IHostingEnvironment hostingEnvironment)
    {
      if (hostingEnvironment == null)
        throw new ArgumentNullException("hostingEnvironment");
      return hostingEnvironment.IsEnvironment(EnvironmentName.Development);
    }

    /// <summary>
    /// Checks if the current hosting environment name is "Staging".
    /// </summary>
    /// <param name="hostingEnvironment">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.IHostingEnvironment" />.</param>
    /// <returns>True if the environment name is "Staging", otherwise false.</returns>
    public static bool IsStaging(this IHostingEnvironment hostingEnvironment)
    {
      if (hostingEnvironment == null)
        throw new ArgumentNullException("hostingEnvironment");
      return hostingEnvironment.IsEnvironment(EnvironmentName.Staging);
    }

    /// <summary>
    /// Checks if the current hosting environment name is "Production".
    /// </summary>
    /// <param name="hostingEnvironment">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.IHostingEnvironment" />.</param>
    /// <returns>True if the environment name is "Production", otherwise false.</returns>
    public static bool IsProduction(this IHostingEnvironment hostingEnvironment)
    {
      if (hostingEnvironment == null)
        throw new ArgumentNullException("hostingEnvironment");
      return hostingEnvironment.IsEnvironment(EnvironmentName.Production);
    }

    /// <summary>
    /// Compares the current hosting environment name against the specified value.
    /// </summary>
    /// <param name="hostingEnvironment">An instance of <see cref="T:Microsoft.AspNetCore.Hosting.IHostingEnvironment" />.</param>
    /// <param name="environmentName">Environment name to validate against.</param>
    /// <returns>True if the specified name is the same as the current environment, otherwise false.</returns>
    public static bool IsEnvironment(this IHostingEnvironment hostingEnvironment, string environmentName)
    {
      if (hostingEnvironment == null)
        throw new ArgumentNullException("hostingEnvironment");
      return string.Equals(hostingEnvironment.EnvironmentName, environmentName, StringComparison.OrdinalIgnoreCase);
    }
  }
}

这是在 VS2017 中 设置 切换 ASPNETCORE_ENVIRONMENT 变量 的另一种方法(@clark-wu 的补充说明答案):

注意:launchSettings.json 在我的案例中有两个配置文件:"IISExpress" 和 "Project",其中定义了 ASPNETCORE_ENVIRONMENT。

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:10000/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/entities",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development" // <-- related to IIS Express profile
      }
    },
    "Project": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/entities",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production" // <-- related to Project profile
      },
      "applicationUrl": "http://localhost:10000/"
    }
  }
}

Official documentation:您可以将ASPNETCORE_ENVIRONMENT设置为任意值,但框架支持三个值:Development、Staging和Production。如果未设置 ASPNETCORE_ENVIRONMENT,则默认为 Production。