How to get the Development/Staging/production Hosting Environment in ConfigureServices

前端 未结 12 1812
时光取名叫无心
时光取名叫无心 2020-12-04 15:51

How do I get the Development/Staging/production Hosting Environment in the ConfigureServices method in Startup?

public void ConfigureServices(IS         


        
相关标签:
12条回答
  • 2020-12-04 16:40

    In .NET Core 2.0 MVC app / Microsoft.AspNetCore.All v2.0.0, you can have environmental specific startup class as described by @vaindil but I don't like that approach.

    You can also inject IHostingEnvironment into StartUp constructor. You don't need to store the environment variable in Program class.

    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());
                }            
            });
    
            ......
        }
    }
    
    0 讨论(0)
  • 2020-12-04 16:42

    TL;DR

    Set an environment variable called ASPNETCORE_ENVIRONMENT with the name of the environment (e.g. Production). Then do one of two things:

    • Inject IHostingEnvironment into Startup.cs, then use that (env here) to check: env.IsEnvironment("Production"). Do not check using env.EnvironmentName == "Production"!
    • Use either separate Startup classes or individual Configure/ConfigureServices functions. If a class or the functions match these formats, they will be used instead of the standard options on that environment.
      • Startup{EnvironmentName}() (entire class) || example: StartupProduction()
      • Configure{EnvironmentName}() || example: ConfigureProduction()
      • Configure{EnvironmentName}Services() || example: ConfigureProductionServices()

    Full explanation

    The .NET Core docs describe how to accomplish this. Use an environment variable called ASPNETCORE_ENVIRONMENT that's set to the environment you want, then you have two choices.

    Check environment name

    From the docs:

    The IHostingEnvironment service provides the core abstraction for working with environments. This service is provided by the ASP.NET hosting layer, and can be injected into your startup logic via Dependency Injection. The ASP.NET Core web site template in Visual Studio uses this approach to load environment-specific configuration files (if present) and to customize the app’s error handling settings. In both cases, this behavior is achieved by referring to the currently specified environment by calling EnvironmentName or IsEnvironment on the instance of IHostingEnvironment passed into the appropriate method.

    NOTE: Checking the actual value of env.EnvironmentName is not recommended!

    If you need to check whether the application is running in a particular environment, use env.IsEnvironment("environmentname") since it will correctly ignore case (instead of checking if env.EnvironmentName == "Development" for example).

    Use separate classes

    From the docs:

    When an ASP.NET Core application starts, the Startup class is used to bootstrap the application, load its configuration settings, etc. (learn more about ASP.NET startup). However, if a class exists named Startup{EnvironmentName} (for example StartupDevelopment), and the ASPNETCORE_ENVIRONMENT environment variable matches that name, then that Startup class is used instead. Thus, you could configure Startup for development, but have a separate StartupProduction that would be used when the app is run in production. Or vice versa.

    In addition to using an entirely separate Startup class based on the current environment, you can also make adjustments to how the application is configured within a Startup class. The Configure() and ConfigureServices() methods support environment-specific versions similar to the Startup class itself, of the form Configure{EnvironmentName}() and Configure{EnvironmentName}Services(). If you define a method ConfigureDevelopment() it will be called instead of Configure() when the environment is set to development. Likewise, ConfigureDevelopmentServices() would be called instead of ConfigureServices() in the same environment.

    0 讨论(0)
  • 2020-12-04 16:44

    I wanted to get the environment in one of my services. It is really easy to do! I just inject it to the constructor like this:

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

    Now later on in the code I can do this:

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

    EDIT:

    Code above is for .NET Core 2. For version 3 you will want to use IWebHostEnvironment.

    0 讨论(0)
  • 2020-12-04 16:46

    This can be accomplished without any extra properties or method parameters, like so:

    public void ConfigureServices(IServiceCollection services)
    {
        IServiceProvider serviceProvider = services.BuildServiceProvider();
        IHostingEnvironment env = serviceProvider.GetService<IHostingEnvironment>();
    
        if (env.IsProduction()) DoSomethingDifferentHere();
    }
    
    0 讨论(0)
  • 2020-12-04 16:51

    per the docs

    Configure and ConfigureServices support environment specific versions of the form Configure{EnvironmentName} and Configure{EnvironmentName}Services:

    You can do something like this...

    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
    }
    
    0 讨论(0)
  • 2020-12-04 16:51

    Since there is no full copy & paste solution yet, based on Joe Audette's answer:

    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
       }
       ...
    }
    
    0 讨论(0)
提交回复
热议问题