如何在ConfigureServices中获得开发/登台/生产托管环境

本文关键字:登台 环境 开发 ConfigureServices | 更新日期: 2023-09-27 18:12:42

如何在启动的ConfigureServices方法中获得开发/登台/生产托管环境?

public void ConfigureServices(IServiceCollection services)
{
    // Which environment are we running under?
}

ConfigureServices方法只接受一个IServiceCollection参数。

如何在ConfigureServices中获得开发/登台/生产托管环境

你可以很容易地在ConfigureServices中访问它,只需在Startup方法期间将其持久化到一个属性中,该方法首先被调用并将其传递进来,然后你可以从ConfigureServices中访问该属性。

public Startup(IWebHostEnvironment env, IApplicationEnvironment appEnv)
{
    ...your code here...
    CurrentEnvironment = env;
}
private IWebHostEnvironment CurrentEnvironment{ get; set; } 
 
public void ConfigureServices(IServiceCollection services)
{
    string envName = CurrentEnvironment.EnvironmentName;
    ... your code here...
}

如果您需要在代码库中不容易访问IHostingEnvironment的地方进行测试,另一种简单的方法是这样做:

bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";

TL;DR

设置名为ASPNETCORE_ENVIRONMENT的环境变量和环境的名称(例如Production)。然后做以下两件事之一:

  • IHostingEnvironment注入Startup.cs,然后使用(这里的env)检查:env.IsEnvironment("Production")不要检查env.EnvironmentName == "Production" !
  • 使用单独的Startup类或单独的Configure/ConfigureServices函数。如果类或函数匹配这些格式,则将使用它们而不是该环境中的标准选项。
    • Startup{EnvironmentName}() (整个类) ||示例:StartupProduction()
    • Configure{EnvironmentName}() || example: ConfigureProduction()
    • Configure{EnvironmentName}Services() ||示例:ConfigureProductionServices()

充分解释

. net核心文档描述了如何实现这一点。使用一个名为ASPNETCORE_ENVIRONMENT的环境变量,它被设置为您想要的环境,那么您有两个选择。

检查环境名称

From the docs:

IHostingEnvironment服务提供了处理环境的核心抽象。该服务由ASP提供。. NET托管层,并且可以通过依赖注入注入到启动逻辑中。ASP。Visual Studio中的。NET Core网站模板使用这种方法来加载特定于环境的配置文件(如果存在的话),并自定义应用程序的错误处理设置。在这两种情况下,这种行为都是通过在传递给适当方法的IHostingEnvironment的实例上调用EnvironmentNameIsEnvironment来引用当前指定的环境来实现的。

注:检查env.EnvironmentName的实际值是不建议 !

如果您需要检查应用程序是否在特定环境中运行,请使用env.IsEnvironment("environmentname"),因为它将正确忽略大小写(而不是检查env.EnvironmentName == "Development")。

使用单独的类

From the docs:

当一个ASP。. NET Core应用程序启动时,Startup类用于引导应用程序,加载其配置设置等。净启动)。但是,如果存在一个名为Startup{EnvironmentName}的类(例如StartupDevelopment),并且ASPNETCORE_ENVIRONMENT环境变量与该名称匹配,则使用该Startup类。因此,您可以为开发配置Startup,但在应用程序在生产环境中运行时使用单独的StartupProduction。反之亦然

除了基于当前环境使用完全独立的Startup类之外,您还可以在Startup类中调整应用程序的配置方式。Configure()ConfigureServices()方法支持与Startup类本身类似的特定于环境的版本,形式为Configure{EnvironmentName}()Configure{EnvironmentName}Services()。如果您定义了一个方法ConfigureDevelopment(),当环境设置为development时,它将被调用,而不是Configure()。同样,在相同的环境中,将调用ConfigureDevelopmentServices()而不是ConfigureServices()

无需任何额外的属性或方法参数即可完成,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    IServiceProvider serviceProvider = services.BuildServiceProvider();
    IHostingEnvironment env = serviceProvider.GetService<IHostingEnvironment>();
    if (env.IsProduction()) DoSomethingDifferentHere();
}

.NET Core 2.0 MVC app/Microsoft.AspNetCore.All v2.0.0中,您可以使用@vaindil描述的环境特定启动类,但我不喜欢这种方法。

也可以将IHostingEnvironment注入到StartUp构造函数中。您不需要将环境变量存储在Program类中。

public class Startup
{
    private readonly IHostingEnvironment _currentEnvironment;
    public IConfiguration Configuration { get; private set; }
    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        _currentEnvironment = env;
        Configuration = configuration;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        ......
        services.AddMvc(config =>
        {
            // Requiring authenticated users on the site globally
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            config.Filters.Add(new AuthorizeFilter(policy));
            // Validate anti-forgery token globally
            config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
            // If it's Production, enable HTTPS
            if (_currentEnvironment.IsProduction())      // <------
            {
                config.Filters.Add(new RequireHttpsAttribute());
            }            
        });
        ......
    }
}

. NET Core 3.0,从ConfigureServicesConfigure访问环境变量要简单得多。

只需将IWebHostEnvironment注入Startup构造函数本身。像这样…

public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        Configuration = configuration;
        _env = env;
    }
    public IConfiguration Configuration { get; }
    private readonly IWebHostEnvironment _env;
    public void ConfigureServices(IServiceCollection services)
    {
        if (_env.IsDevelopment())
        {
            //development
        }
    }
    public void Configure(IApplicationBuilder app)
    {
        if (_env.IsDevelopment())
        {
            //development
        }
    }
}

参考:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0#inject-iwebhostenvironment-into-the-startup-class

在NET6中,Startup和Program已经合并为一个文件,Startup中不再有ConfigureServices方法。现在您可以简单地使用

builder.Environment.IsProduction() 
builder.Environment.IsStaging()
builder.Environment.IsDevelopment()

第一行之后

var builder = WebApplication.CreateBuilder(args);
from the docs

Configure和ConfigureServices支持特定于环境的版本配置{EnvironmentName}和配置{EnvironmentName}服务:

你可以这样做…

public void ConfigureProductionServices(IServiceCollection services)
{
    ConfigureCommonServices(services);
    
    //Services only for production
    services.Configure();
}
public void ConfigureDevelopmentServices(IServiceCollection services)
{
    ConfigureCommonServices(services);
    
    //Services only for development
    services.Configure();
}
public void ConfigureStagingServices(IServiceCollection services)
{
    ConfigureCommonServices(services);
    
    //Services only for staging
    services.Configure();
}
private void ConfigureCommonServices(IServiceCollection services)
{
    //Services common to each environment
}

我想在我的一个服务中获得这个环境。这真的很容易做到!我只需要像这样把它注入构造函数:

    private readonly IHostingEnvironment _hostingEnvironment;
    public MyEmailService(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }

在后面的代码中我可以这样做:

if (_hostingEnvironment.IsProduction()) {
    // really send the email.
}
else {
    // send the email to the test queue.
}

编辑:

上面的代码是针对。net Core 2的。对于版本3,您将希望使用IWebHostEnvironment .

因为没有完整的副本&根据Joe Audette的回答,粘贴解决方案:

public IWebHostEnvironment Environment { get; }
public Startup(IWebHostEnvironment environment, IConfiguration configuration)
{
   Environment = environment;
   ...
}
public void ConfigureServices(IServiceCollection services)
{
   if (Environment.IsDevelopment())
   {
       // Do something
   }else{
       // Do something
   }
   ...
}

主机环境来自于ASPNET_ENV环境变量,该变量在启动时使用IHostingEnvironment可用。IsEnvironment扩展方法,或IsDevelopment或IsProduction的相应便利方法之一。在Startup()或ConfigureServices call中保存你需要的内容:

var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");

以防有人也在看这个。在。net core 3+中,这些大部分都过时了。更新方式为:

public void Configure(
    IApplicationBuilder app,
    IWebHostEnvironment env,
    ILogger<Startup> logger)
{
    if (env.EnvironmentName == Environments.Development)
    {
        // logger.LogInformation("In Development environment");
    }
}

在Dotnet Core 2.0中,Startup-constructor只需要一个iconconfiguration -parameter。

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

如何读取主机环境?我在ConfigureAppConfiguration期间将其存储在Program-class中(使用完整的BuildWebHost而不是WebHost.CreateDefaultBuilder):

public class Program
{
    public static IHostingEnvironment HostingEnvironment { get; set; }
    public static void Main(string[] args)
    {
        // Build web host
        var host = BuildWebHost(args);
        host.Run();
    }
    public static IWebHost BuildWebHost(string[] args)
    {
        return new WebHostBuilder()
            .UseConfiguration(new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("hosting.json", optional: true)
                .Build()
            )
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                var env = hostingContext.HostingEnvironment;
                // Assigning the environment for use in ConfigureServices
                HostingEnvironment = env; // <---
                config
                  .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
                if (env.IsDevelopment())
                {
                    var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                    if (appAssembly != null)
                    {
                        config.AddUserSecrets(appAssembly, optional: true);
                    }
                }
                config.AddEnvironmentVariables();
                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
            .ConfigureLogging((hostingContext, builder) =>
            {
                builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                builder.AddConsole();
                builder.AddDebug();
            })
            .UseIISIntegration()
            .UseDefaultServiceProvider((context, options) =>
            {
                options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
            })
            .UseStartup<Startup>()
            .Build();
    }

Ant然后像这样在ConfigureServices中读取它:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}

另一种方法是直接从Configuration["ASPNETCORE_ENVIRONMENT"]的配置中读取环境名称。这适用于任何可以访问配置的地方。

public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
    Console.WriteLine(Configuration["ASPNETCORE_ENVIRONMENT"]);
}

前提条件是主机是用program .cs中的host . createdefaultbuilder()创建的,这是ASP的默认设置。. NET Core 3.0(和5.0)web应用程序。如果使用了另一个构建器,则可以在program .cs中使用AddEnvironmentVariables()添加环境变量。

在.NET6.0中使用如下:

var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");

显示"Development"

变量"dev_environment";也将在开发环境中设置为1。

对于blazor服务器应用程序,我这样做了:直接在命名空间声明下添加Startup.cs

namespace myProjectName.Server
public static class myGlobals
{
    public static bool isDevelopment = true;
}

Startup.cs找到Configure方法和env.IsDevelopment的现有检查,并将上面声明的static isDeveloment设置为truefalse

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
           myGlobals.isDevelopment = true;
        }
        else false

ApplicationUser中初始化数据库连接或其他任何地方

        if (myGlobals.isDevelopment)
        {