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

16

360

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

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

The ConfigureServices method only takes a single IServiceCollection parameter.

Blotchy answered 13/9, 2015 at 10:56 Comment(3)
why can't IHostingEnvironment just be injected into ConfigureServices? oversight? or a reason we need to be aware of?Volcanism
See MSFT docs learn.microsoft.com/en-us/aspnet/core/fundamentals/environmentsFart
Use using Microsoft.Extensions.Hosting; if you are using IWebHostEnvironment. It will give you IsDevelopment/IsProduction/IsStaging etc checks.Woodenhead
P
419

You can easily access it in ConfigureServices, just persist it to a property during Startup method which is called first and gets it passed in, then you can access the property from 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...
}
Palladino answered 14/9, 2015 at 1:49 Comment(11)
Per the docs, this method should not be used. You should instead be using CurrentEnvironment.IsEnvironment("environmentname").Stepup
or CurrentEnvironment.IsDevelopment() / CurrentEnvironment.IsProduction()Volcanism
@Stepup - the docs you reference don't say this method should not be used. Your example simply ignores casing, which is preferable in many cases but not a commandmentUntouched
@Untouched Okay, it doesn't explicitly say to NOT use this method, but it says to use the other method INSTEAD. That's virtually the same thing.Stepup
Formally, Startup is not a method, it's a constructor.Alcala
deprecated IHostingEnvironment env use IWebHostEnvironment env insteadHephzipa
Read following answer TL;DR with correct solution Configure{EnvironmentName}() || example: ConfigureProduction().Fielder
The messaging about IHostingEnvironment being deprecated does appear as described by @Mark Schultheiss, but depending on what you care about, you can use IHostEnvironment too, which is a slightly leaner base class for IWebHostEnvironment.Finical
@tom, yes, also deprecation notice can be seen here learn.microsoft.com/en-us/dotnet/api/…Hephzipa
IApplicationEnvironment is not recognizedTessera
This is what docs says, and there is no such sentence that leads us not to use IWebHostEnvironment injectionInject IWebHostEnvironment into the Startup constructor. This approach is useful when the app requires configuring Startup for only a few environments with minimal code differences per environment.Actino
S
107

If you need to test this somewhere in your codebase that doesn't have easy access to the IHostingEnvironment, another easy way to do it is like this:

bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
Sunderland answered 10/4, 2019 at 19:34 Comment(4)
well, short way! Keep in mind the variable name is different between "asp.net core" and "asp.net"Mcdade
Wow, what a nice ideaDeport
this code only works if there is a environment variable already set, in case your project will be published using ISS on windows server may this should wont the case, in this case I advice you to set the variable on Program.cs classKarlenekarlens
This is great because it doesn't depend a specific version of .Net Core.Galliwasp
S
80

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.

Stepup answered 5/8, 2016 at 19:27 Comment(2)
Has this changed much with the .NET 6 (non-core) release?Preparedness
I don't think so. still following this pattern. @DavidMaysMatildamatilde
A
43

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();
}
Andes answered 28/2, 2018 at 16:19 Comment(4)
the best answer ever. thanxBrotherhood
This throws the following warning in .NET Core 3.0: Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.Dishrag
deprecated IHostingEnvironment env use IWebHostEnvironment env insteadHephzipa
Calling BuildServiceProvider is not recommended! see this article for more details.Acie
C
36

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

        ......
    }
}
Constrictive answered 3/10, 2017 at 18:59 Comment(3)
Details can be viewed in: learn.microsoft.com/pt-br/aspnet/core/fundamentals/…Encephalic
Here is the english link posted by André: learn.microsoft.com/en-us/aspnet/core/fundamentals/…Niedersachsen
deprecated IHostingEnvironment env use IWebHostEnvironment env insteadHephzipa
H
36

Starting from ASP.NET Core 3.0, it is much simpler to access the environment variable from both ConfigureServices and Configure.

Simply inject IWebHostEnvironment into the Startup constructor itself. Like so...

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
        }
    }
}

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

Hydrus answered 23/11, 2020 at 9:48 Comment(2)
but its telling on Development or not Development (Staging, Production, VST.......). It doesn't tell whether it's production or Staging or.....?Sansen
@viveknuna Simply create your own IsStaging, IsXXXXX, etc and make sure you have the matching ASPNETCORE_ENVIRONMENT to check against.Hydrus
B
30

In NET6, Startup and Program have merged into a single file, there is no ConfigureServices method in Startup anymore. Now you can simply use

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

right after the first line

var builder = WebApplication.CreateBuilder(args);
Bigelow answered 15/3, 2022 at 1:4 Comment(0)
M
24

from 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
}
Mikkimiko answered 21/3, 2018 at 20:45 Comment(4)
This is the nicest conventionOblation
I dont see anything about this in the docs.....Superannuation
@RichardDuerr This answer is about 4 years old now and the docs have changed. I've updated the linkMikkimiko
Thanks, I tried looking and couldn't find it. Must have been blind haSuperannuation
D
23

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.

Despondency answered 10/12, 2018 at 20:42 Comment(2)
I'm curious why this is receiving down votes. Is there something about this that is wrong or bad practice? I want to learn.Despondency
I'm personally glad you included this because it helped in my use case, but my guess as to why you were downvoted is that it's not answering the original question as asked.Merna
O
8

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
   }
   ...
}
Ocotillo answered 2/11, 2020 at 11:34 Comment(0)
D
6

The hosting environment comes from the ASPNET_ENV environment variable, which is available during Startup using the IHostingEnvironment.IsEnvironment extension method, or one of the corresponding convenience methods of IsDevelopment or IsProduction. Either save what you need in Startup(), or in ConfigureServices call:

var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");
Domella answered 13/9, 2015 at 12:24 Comment(5)
IHostingEnvironment is not available in ConfigureServices.Blotchy
No, it's not. Refer back to my answer on how to deal with it.Domella
The environment variable is now "ASPNETCORE_ENVIRONMENT"Extrinsic
deprecated IHostingEnvironment env use IWebHostEnvironment env insteadHephzipa
Works for me on dotnet core 6. I placed it in my program.cs which was then passed into my return WebHost.CreateDefaultBuilder(args) function call with environment as a parameterHoliday
S
4

Just in case someone is looking to this too. In .net core 3+ most of this is obsolete. The update way is:

public void Configure(
    IApplicationBuilder app,
    IWebHostEnvironment env,
    ILogger<Startup> logger)
{
    if (env.EnvironmentName == Environments.Development)
    {
        // logger.LogInformation("In Development environment");
    }
}
Susurration answered 31/3, 2020 at 5:29 Comment(2)
The question specifically asks about ConfigureServices, not Configure.Croaker
This doesn't work for ConfigureServices, because you can't inject IWebHostEnvironment in ConfigureServices. So this doesn't answer the question.Dimitrovo
A
4

Another way is to read the environment name directly from the configuration with Configuration["ASPNETCORE_ENVIRONMENT"]. This works everywhere where you can access configuration.

public IConfiguration Configuration { get; }

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

Prerequisite is that the host was created with Host.CreateDefaultBuilder() in Programm.cs which is the default for ASP.NET Core 3.0 (and 5.0) web apps. If another builder is used the envars can be added with AddEnvironmentVariables() in Programm.cs.

Amaleta answered 3/9, 2021 at 12:34 Comment(0)
N
3

In Dotnet Core 2.0 the Startup-constructor only expects a IConfiguration-parameter.

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

How to read hosting environment there? I store it in Program-class during ConfigureAppConfiguration (use full BuildWebHost instead of 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 then reads it in ConfigureServices like this:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}
Nanci answered 26/9, 2017 at 15:30 Comment(1)
deprecated IHostingEnvironment env use IWebHostEnvironment env insteadHephzipa
I
0

In .NET6.0 Use the following:

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

This will say "Development" if it is in development mode.

The variable "DEV_ENVIRONMENT" also will be set to 1 in dev environment.

Intended answered 21/2, 2023 at 15:38 Comment(0)
D
-2

For a blazor server app I did this: Startup.cs directly under the namespace declaration add

namespace myProjectName.Server

public static class myGlobals

{
    public static bool isDevelopment = true;
}

Startup.cs find the Configure method and the existing check for env.IsDevelopment and set the static isDeveloment declared above to true or false.

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

In ApplicationUser when you are initializing the database connection or anywhere else

        if (myGlobals.isDevelopment)
        {
Disenable answered 26/6, 2021 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.