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

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

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

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

186075 次浏览

宿主环境来自ASPNET_ENV环境变量,在启动过程中使用IHostingEnvironment可用。IsEnvironment扩展方法,或IsDevelopment或IsProduction中相应的方便方法之一。在Startup()中保存你需要的东西,或者在ConfigureServices调用中保存:

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

你可以很容易地在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...
}

博士TL;

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

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

    完整的解释

    . net Core文档请描述如何实现这一点。使用一个名为ASPNETCORE_ENVIRONMENT的环境变量,它被设置为你想要的环境,然后你有两个选择。

    检查环境名称

    来自文档:

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

    注意:检查env.EnvironmentName的实际值建议为 !

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

    使用单独的类

    来自文档:

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

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

在Dotnet Core 2.0中,启动构造函数只需要一个iconfigure -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();
}

.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());
}
});


......
}
}

这可以在没有任何额外属性或方法参数的情况下完成,如下所示:

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


if (env.IsProduction()) DoSomethingDifferentHere();
}

文档

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

你可以这样做……

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

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

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

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

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

由于没有完整的副本&根据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
}
...
}

从ASP开始。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

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

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)
{

另一种方法是使用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. cs的默认值。NET Core 3.0(和5.0)web应用程序。如果使用其他构建器,则可以使用program .cs中的AddEnvironmentVariables()添加envars。

在NET6中,启动和程序已经合并到一个文件中,启动中不再有ConfigureServices方法。现在你可以简单地使用

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

就在第一行之后

var builder = WebApplication.CreateBuilder(args);