如何在ConfigureServices中获得开发/登台/生产托管环境
本文关键字:登台 环境 开发 ConfigureServices | 更新日期: 2023-09-27 18:12:42
如何在启动的ConfigureServices
方法中获得开发/登台/生产托管环境?
public void ConfigureServices(IServiceCollection services)
{
// Which environment are we running under?
}
ConfigureServices
方法只接受一个IServiceCollection
参数。
你可以很容易地在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
的实例上调用EnvironmentName
或IsEnvironment
来引用当前指定的环境来实现的。
注:检查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,从ConfigureServices
和Configure
访问环境变量要简单得多。
只需将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);
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
设置为true
或false
。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
myGlobals.isDevelopment = true;
}
else false
在ApplicationUser
中初始化数据库连接或其他任何地方
if (myGlobals.isDevelopment)
{