Como obter o ambiente de hospedagem de desenvolvimento / armazenamento temporário / produção no ConfigureServices


170

Como obtenho o ambiente de hospedagem de desenvolvimento / armazenamento temporário / produção no ConfigureServicesmétodo em Inicialização?

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

O ConfigureServicesmétodo usa apenas um único IServiceCollectionparâmetro.


4
por que não pode IHostingEnvironmentsimplesmente ser injetado no ConfigureServices? supervisão? ou um motivo pelo qual precisamos estar cientes?
— Simon_Weaver

Respostas:


225

Você pode acessá-lo facilmente no ConfigureServices, apenas persistir em uma propriedade durante o método Startup, que é chamada primeiro e transferida, e você pode acessar a propriedade no 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
De acordo com os documentos , esse método não deve ser usado. Você deveria estar usando CurrentEnvironment.IsEnvironment("environmentname").
— vaindil

28
ou CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
— Simon_Weaver 30/11

3
@vaindil - os documentos que você referencia não dizem que esse método não deve ser usado. Seu exemplo simplesmente ignora caixa, que é preferível em muitos casos, mas não um mandamento
— Coruscate5

3
@ Coruscate5 Ok, ele não diz explicitamente para NÃO usar esse método, mas diz para usar o outro método INSTEAD. Isso é praticamente a mesma coisa.
— vaindil

8
depredado IHostingEnvironment env usar IWebHostEnvironment env vez
— Mark Schultheiss

56

TL; DR

Defina uma variável de ambiente chamada ASPNETCORE_ENVIRONMENTcom o nome do ambiente (por exemplo Production). Depois, faça uma de duas coisas:

  • Inject IHostingEnvironmentpara Startup.cs, em seguida, usar isso ( envaqui) para verificar: env.IsEnvironment("Production"). Não verifique usando env.EnvironmentName == "Production"!
  • Use Startupclasses separadas ou individuais Configure/ ConfigureServicesfunções. Se uma classe ou as funções corresponderem a esses formatos, elas serão usadas em vez das opções padrão nesse ambiente.
    • Startup{EnvironmentName}() (turma inteira) || exemplo:StartupProduction()
    • Configure{EnvironmentName}()|| exemplo:ConfigureProduction()
    • Configure{EnvironmentName}Services()|| exemplo:ConfigureProductionServices()

Explicação completa

Os documentos do .NET Core descrevem como fazer isso . Use uma variável de ambiente chamada ASPNETCORE_ENVIRONMENTdefinida para o ambiente que você deseja, e então você tem duas opções.

Verifique o nome do ambiente

Dos documentos :

O IHostingEnvironmentserviço fornece a abstração principal para trabalhar com ambientes. Este serviço é fornecido pela camada de hospedagem ASP.NET e pode ser injetado na sua lógica de inicialização via Injeção de Dependência. O modelo de site ASP.NET Core no Visual Studio usa essa abordagem para carregar arquivos de configuração específicos do ambiente (se houver) e para personalizar as configurações de tratamento de erros do aplicativo. Nos dois casos, esse comportamento é alcançado consultando o ambiente atualmente especificado chamando EnvironmentNameou IsEnvironmentna instância de IHostingEnvironmentpassado para o método apropriado.

NOTA: Nãoenv.EnvironmentName é recomendável verificar o valor real de !

Se você precisar verificar se o aplicativo está sendo executado em um ambiente específico, use, env.IsEnvironment("environmentname")pois ele ignorará corretamente o caso (em vez de verificar se, env.EnvironmentName == "Development"por exemplo).

Use classes separadas

Dos documentos :

Quando um aplicativo ASP.NET Core é iniciado, a Startupclasse é usada para inicializar o aplicativo, carregar suas definições de configuração etc. ( saiba mais sobre a inicialização do ASP.NET ). No entanto, se existir uma classe chamada Startup{EnvironmentName}(por exemplo StartupDevelopment), e a ASPNETCORE_ENVIRONMENTvariável de ambiente corresponder a esse nome, essa Startupclasse será usada. Assim, você pode configurar Startuppara desenvolvimento, mas ter um separado StartupProductionque seria usado quando o aplicativo for executado em produção. Ou vice-versa.

Além de usar uma Startupclasse totalmente separada com base no ambiente atual, você também pode fazer ajustes na forma como o aplicativo é configurado dentro de uma Startupclasse. Os métodos Configure()e ConfigureServices()suportam versões específicas do ambiente semelhantes à Startupprópria classe, da forma Configure{EnvironmentName}()e Configure{EnvironmentName}Services(). Se você definir um método, ConfigureDevelopment()ele será chamado em vez de Configure()quando o ambiente estiver definido para desenvolvimento. Da mesma forma, ConfigureDevelopmentServices()seria chamado em vez de ConfigureServices()no mesmo ambiente.


29

No .NET Core 2.0MVC app / Microsoft.AspNetCore.Allv2.0.0, você pode ter uma classe de inicialização específica do ambiente, conforme descrito por @vaindil, mas eu não gosto dessa abordagem.

Você também pode injetar IHostingEnvironmentno StartUpconstrutor. Você não precisa armazenar a variável de ambiente na Programclasse.

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

        ......
    }
}


Aqui está o link em inglês publicado por André: docs.microsoft.com/en-us/aspnet/core/fundamentals/…
— ahong

1
depredado IHostingEnvironment env usar IWebHostEnvironment env vez
— Mark Schultheiss

21

Isso pode ser realizado sem propriedades extras ou parâmetros de método, como:

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

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

2
a melhor resposta de sempre. thanx
— Shady Sherif

7
Isso lança o seguinte aviso no .NET Core 3.0: Chamar 'BuildServiceProvider' do código do aplicativo resulta em uma cópia adicional dos serviços singleton sendo criados. Considere alternativas como serviços de injeção de dependência como parâmetros para 'Configurar'.
— Eternal21

2
depredado IHostingEnvironment env usar IWebHostEnvironment env vez
— Mark Schultheiss

19

Se você precisar testar isso em algum lugar da sua base de código que não tenha acesso fácil ao IHostingEnvironment, outra maneira fácil de fazer isso é:

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

bem, caminho curto! Lembre-se de que o nome da variável é diferente entre "asp.net core" e "asp.net"
— nmDat 30/06/19

14

de acordo com os documentos

O Configure e o ConfigureServices suportam versões específicas do ambiente do formulário Configure os Serviços {EnvironmentName} e Configure {EnvironmentName}:

Você pode fazer algo assim ...

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
}

Esta é a convenção mais legal
— Stuart.Sklinar

11

Eu queria obter o ambiente em um dos meus serviços. É realmente fácil de fazer! Eu apenas injeto no construtor assim:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Agora, mais tarde, no código, eu posso fazer isso:

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

EDITAR:

O código acima é para o .NET Core 2. Para a versão 3, você desejará usar IWebHostEnvironment.


5

O ambiente de hospedagem vem da variável de ambiente ASPNET_ENV, disponível durante a Inicialização, usando o método de extensão IHostingEnvironment.IsEnvironment ou um dos métodos de conveniência correspondentes de IsDevelopment ou IsProduction. Salve o que você precisa em Startup () ou na chamada ConfigureServices:

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

IHostingEnvironmentnão está disponível em ConfigureServices.
— Muhammad Rehan Saeed

1
Não, não é. Consulte minha resposta sobre como lidar com isso.
— Jeff Dunlop

8
A variável de ambiente é agora "ASPNETCORE_ENVIRONMENT"
— Anthony

deprovado IHostingEnvironment env usar IWebHostEnvironment env vez
— Mark Schultheiss

5

Apenas no caso de alguém estar olhando para isso também. No .net core 3+, a maior parte disso é obsoleta. A maneira de atualização é:

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

2

No Dotnet Core 2.0, o construtor Startup espera apenas um parâmetro IConfiguration.

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

Como ler o ambiente de hospedagem lá? Eu o armazeno na classe Program durante o ConfigureAppConfiguration (use BuildWebHost completo em vez de 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();
    }

O Ant lê-o no ConfigureServices assim:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}

deprecated IHostingEnvironment env use IWebHostEnvironment env em vez disso
— Mark Schultheiss
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.