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


170

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

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

ConfigureServices方法仅采用一个IServiceCollection参数。


4
为什么不能IHostingEnvironment只注入ConfigureServices?监督?还是我们需要注意的原因?
Simon_Weaver

Answers:


225

您可以在ConfigureServices中轻松访问它,只需在启动方法期间将其持久保存到属性中,该方法将首先被调用并传递给它,然后您可以从ConfigureServices中访问该属性。

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    ...your code here...
    CurrentEnvironment = env;
}

private IHostingEnvironment CurrentEnvironment{ get; set; } 

public void ConfigureServices(IServiceCollection services)
{
    string envName = CurrentEnvironment.EnvironmentName;
    ... your code here...
}

13
根据文档,不应使用此方法。您应该改为使用CurrentEnvironment.IsEnvironment("environmentname")
vaindil '16

28
CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver

3
@vaindil-您引用的文档没有说不应使用此方法。您的示例只是忽略了大小写,这在许多情况下是可取的,但不是诫命
Coruscate5

3
@ Coruscate5好的,它没有明确表示不使用此方法,但表示要使用另一种方法INSTEAD。几乎是同一回事。
vaindil

8
不推荐使用的IHostingEnvironment env使用IWebHostEnvironment env
Mark Schultheiss

56

TL; DR

设置一个名为环境ASPNETCORE_ENVIRONMENT名称的环境变量(例如Production)。然后执行以下两项操作之一:

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

完整说明

.NET Core文档描述了如何完成此任务。使用一个称为环境变量,将ASPNETCORE_ENVIRONMENT其设置为所需的环境,然后有两种选择。

检查环境名称

从文档

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

注意:检查的实际值env.EnvironmentName推荐!

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

使用单独的类

从文档

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

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


29

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

您也可以注入IHostingEnvironmentStartUp构造函数。您无需将环境变量存储在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());
            }            
        });

        ......
    }
}


这是张贴安德烈英文链接:docs.microsoft.com/en-us/aspnet/core/fundamentals/...
阿旬

1
不推荐使用的IHostingEnvironment env使用IWebHostEnvironment env
Mark Schultheiss

21

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

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

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

2
有史以来最好的答案。thanx
Shady Sherif

7
这在.NET Core 3.0中引发以下警告:从应用程序代码调用“ BuildServiceProvider”会导致创建单例服务的其他副本。考虑将诸如依赖项注入服务之类的替代方案作为“配置”的参数。
Eternal21 '19

2
不推荐使用的IHostingEnvironment env使用IWebHostEnvironment env
Mark Schultheiss

19

如果您需要在代码库中无法轻松访问IHostingEnvironment的位置进行测试,则另一种简单的方法如下:

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

好吧,短路!请记住,变量名称在“ asp.net核心”和“ asp.net”之间是不同的
nmDat

14

根据文档

Configure和ConfigureServices支持特定于环境的版本,格式为Configure {EnvironmentName}和Configure {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
}

这是最好的约定
Stuart.Sklinar

11

我想在我的一项服务中获得环境。真的很容易做到!我只是将其注入到构造函数中,如下所示:

    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 Core2。对于版本3,您将需要使用IWebHostEnvironment


5

宿主环境来自ASPNET_ENV环境变量,该变量在启动过程中可以使用IHostingEnvironment.IsEnvironment扩展方法或IsDevelopment或IsProduction的相应便捷方法之一提供。在Startup()或ConfigureServices调用中保存所需的内容:

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

IHostingEnvironment在中不可用ConfigureServices
穆罕默德·雷汉

1
不,这不对。请返回我对如何处理的答案。
杰夫·邓洛普

8
环境变量现在为“ ASPNETCORE_ENVIRONMENT”
安东尼

不推荐使用的IHostingEnvironment env使用IWebHostEnvironment env
Mark Schultheiss

5

以防万一有人也在寻找这个。在.net core 3+中,大多数功能已过时。更新方式为:

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

2

在Dotnet Core 2.0中,启动构造函数仅需要IConfiguration参数。

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

如何在那里阅读托管环境?我在ConfigureAppConfiguration期间将其存储在程序类中(使用完整的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();
}

不推荐使用的IHostingEnvironment env使用IWebHostEnvironment env
Mark Schultheiss
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.