Jak uzyskać środowisko hostingu deweloperskiego / przejściowego / produkcyjnego w programie ConfigureServices

171

Jak uzyskać środowisko hostingu deweloperskiego / przejściowego / produkcyjnego w ConfigureServicesmetodzie w programie Startup?

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

ConfigureServicesMetoda zajmuje tylko jeden IServiceCollectionparametr.

Muhammad Rehan Saeed
źródło
4
dlaczego nie można IHostingEnvironmentpo prostu wstrzyknąć do ConfigureServices? przeoczenie? lub powód, którego musimy być świadomi?
Simon_Weaver
3
Zobacz dokumentację MSFT docs.microsoft.com/en-us/aspnet/core/fundamentals/environments
RickAndMSFT,

Odpowiedzi:

225

Możesz łatwo uzyskać do niego dostęp w ConfigureServices, po prostu utrwal go we właściwości podczas metody Startup, która jest wywoływana jako pierwsza i pobiera ją, a następnie możesz uzyskać dostęp do właściwości z 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...
}
Joe Audette
źródło
13
Zgodnie z dokumentacją ta metoda nie powinna być używana. Zamiast tego powinieneś używać CurrentEnvironment.IsEnvironment("environmentname").
vaindil
28
lub CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver
3
@vaindil - dokumenty, do których się odwołujesz, nie mówią, że ta metoda nie powinna być używana. Twój przykład po prostu ignoruje wielkość liter, która jest preferowana w wielu przypadkach, ale nie jest przykazaniem
Coruscate5
3
@ Coruscate5 Okay, nie mówi wprost, aby NIE używać tej metody, ale mówi, że należy używać innej metody ZAMIAST. To praktycznie to samo.
vaindil
8
przestarzałe środowisko IHostingEnvironment używa zamiast tego środowiska IWebHostEnvironment
Mark Schultheiss
56

TL; DR

Ustaw zmienną środowiskową o nazwie ASPNETCORE_ENVIRONMENTz nazwą środowiska (np Production.). Następnie wykonaj jedną z dwóch czynności:

  • Wprowadzić IHostingEnvironmentdo Startup.cs, a następnie użyć że ( envtutaj) w celu sprawdzenia: env.IsEnvironment("Production"). Nie sprawdzaj za pomocą env.EnvironmentName == "Production"!
  • Użyj oddzielnych Startupklas lub indywidualnych Configure/ ConfigureServicesfunkcji. Jeśli klasa lub funkcje pasują do tych formatów, zostaną użyte zamiast standardowych opcji w tym środowisku.
    • Startup{EnvironmentName}() (cała klasa) || przykład:StartupProduction()
    • Configure{EnvironmentName}()|| przykład:ConfigureProduction()
    • Configure{EnvironmentName}Services()|| przykład:ConfigureProductionServices()

Pełne wyjaśnienie

W dokumentacji .NET Core opisano, jak to osiągnąć . Użyj zmiennej środowiskowej o nazwie, ASPNETCORE_ENVIRONMENTktóra jest ustawiona na żądane środowisko, wtedy masz dwie możliwości.

Sprawdź nazwę środowiska

Z dokumentów :

IHostingEnvironmentUsługa zapewnia podstawową abstrakcję do pracy ze środowiskami. Ta usługa jest świadczona przez warstwę hostingu ASP.NET i można ją wstrzyknąć do logiki uruchamiania za pomocą iniekcji zależności. Szablon witryny sieci Web ASP.NET Core w programie Visual Studio używa tego podejścia do ładowania plików konfiguracji specyficznych dla środowiska (jeśli są obecne) i dostosowywania ustawień obsługi błędów aplikacji. W obu przypadkach to zachowanie uzyskuje się poprzez odwołanie się do aktualnie określonego środowiska przez wywołanie EnvironmentNamelub IsEnvironmentna wystąpienie IHostingEnvironmentprzekazane do odpowiedniej metody.

UWAGA: Sprawdzanie rzeczywistą wartość env.EnvironmentNamejest nie zalecane!

Jeśli chcesz sprawdzić, czy aplikacja działa w określonym środowisku, użyj, env.IsEnvironment("environmentname")ponieważ poprawnie zignoruje wielkość liter (zamiast sprawdzać, czy env.EnvironmentName == "Development"na przykład).

Użyj oddzielnych klas

Z dokumentów :

Po uruchomieniu aplikacji ASP.NET Core Startupklasa jest używana do ładowania aplikacji, ładowania jej ustawień konfiguracyjnych itp. ( Dowiedz się więcej o uruchamianiu ASP.NET ). Jeśli jednak klasa istnieje o nazwie Startup{EnvironmentName}(na przykład StartupDevelopment), a ASPNETCORE_ENVIRONMENTzmienna środowiskowa jest zgodna z tą nazwą, Startupzamiast niej zostanie użyta ta klasa. W związku z tym można skonfigurować Startupdo programowania, ale mieć oddzielny StartupProduction, który będzie używany, gdy aplikacja jest uruchamiana w środowisku produkcyjnym. Lub odwrotnie.

Oprócz używania całkowicie oddzielnej Startupklasy opartej na bieżącym środowisku, możesz również wprowadzić zmiany w sposobie konfiguracji aplikacji w Startupklasie. Configure()I ConfigureServices()metody wspierania środowiska specyficzne wersje podobne do Startupsamej klasy, o formie Configure{EnvironmentName}()i Configure{EnvironmentName}Services(). Jeśli zdefiniujesz metodę ConfigureDevelopment(), zostanie ona wywołana, a nie Configure()wtedy, gdy środowisko jest ustawione na programowanie. Podobnie ConfigureDevelopmentServices()zostałby wywołany zamiast ConfigureServices()w tym samym środowisku.

vaindil
źródło
29

W .NET Core 2.0aplikacji MVC / Microsoft.AspNetCore.Allv2.0.0 możesz mieć klasę startową specyficzną dla środowiska, zgodnie z opisem @vaindil, ale nie podoba mi się to podejście.

Możesz także wstrzyknąć IHostingEnvironmentdo StartUpkonstruktora. Nie musisz przechowywać zmiennej środowiskowej w Programklasie.

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

        ......
    }
}
David Liang
źródło
1
Szczegóły można obejrzeć w: docs.microsoft.com/pt-br/aspnet/core/fundamentals/ ...
André Morales
Oto link w języku angielskim opublikowany przez André: docs.microsoft.com/en-us/aspnet/core/fundamentals/ ...
ahong
1
przestarzałe środowisko IHostingEnvironment używa zamiast tego środowiska IWebHostEnvironment
Mark Schultheiss
21

Można to osiągnąć bez żadnych dodatkowych właściwości lub parametrów metody, na przykład:

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

    if (env.IsProduction()) DoSomethingDifferentHere();
}
edicius6
źródło
2
najlepsza odpowiedź w historii. thanx
Shady Sherif
7
Powoduje to zgłoszenie następującego ostrzeżenia w .NET Core 3,0: Wywołanie „BuildServiceProvider” z kodu aplikacji powoduje utworzenie dodatkowej kopii pojedynczych usług. Rozważ alternatywy, takie jak usługi wstrzykiwania zależności, jako parametry opcji „Konfiguruj”.
Eternal21
2
przestarzałe środowisko IHostingEnvironment używa zamiast tego środowiska IWebHostEnvironment
Mark Schultheiss
19

Jeśli chcesz to przetestować gdzieś w swojej bazie kodu, która nie ma łatwego dostępu do IHostingEnvironment, inny łatwy sposób na zrobienie tego jest następujący:

bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
Patrick
źródło
dobrze, krótko! Pamiętaj, że nazwa zmiennej różni się między „asp.net core” i „asp.net”
nmDat
15

zgodnie z dokumentacją

Skonfiguruj i ConfigureServices obsługujące środowisko wersje formularza Konfiguruj {EnvironmentName} i konfiguruj {EnvironmentName} usługi:

Możesz zrobić coś takiego ...

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
}
But
źródło
1
To najmilszy konwent
Stuart.Sklinar
11

Chciałem uzyskać środowisko w jednej z moich usług. To naprawdę proste! Po prostu wstrzykuję to konstruktorowi w ten sposób:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Teraz w dalszej części kodu mogę to zrobić:

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

EDYTOWAĆ:

Powyższy kod dotyczy platformy .NET Core 2. W przypadku wersji 3 będziesz chciał użyć IWebHostEnvironment.

Pęto
źródło
5

Środowisko hostingu pochodzi ze zmiennej środowiskowej ASPNET_ENV, która jest dostępna podczas uruchamiania przy użyciu metody rozszerzenia IHostingEnvironment.IsEnvironment lub jednej z odpowiednich wygodnych metod IsDevelopment lub IsProduction. Zapisz to, czego potrzebujesz, w Startup () lub w wywołaniu ConfigureServices:

var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");
Jeff Dunlop
źródło
IHostingEnvironmentnie jest dostępny w ConfigureServices.
Muhammad Rehan Saeed
1
Nie, nie jest. Wróć do mojej odpowiedzi, jak sobie z tym poradzić.
Jeff Dunlop,
8
Zmienna środowiskowa to teraz „ASPNETCORE_ENVIRONMENT”
Anthony
przestarzałe środowisko IHostingEnvironment używa zamiast tego środowiska IWebHostEnvironment
Mark Schultheiss
5

Na wypadek, gdyby ktoś też tego szukał. W .net core 3+ większość tego jest przestarzała. Sposób aktualizacji to:

public void Configure(
    IApplicationBuilder app,
    IWebHostEnvironment env,
    ILogger<Startup> logger)
{
    if (env.EnvironmentName == Environments.Development)
    {
        // logger.LogInformation("In Development environment");
    }
}
Vahagn Nahapetyan
źródło
2

W Dotnet Core 2,0 Konstruktor startowy oczekuje tylko parametru IConfiguration.

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

Jak czytać tam środowisko hostingowe? Przechowuję go w klasie Program podczas ConfigureAppConfiguration (użyj pełnego BuildWebHost zamiast 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();
    }

Następnie Ant czyta go w ConfigureServices w ten sposób:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}
toralux
źródło
przestarzałe środowisko IHostingEnvironment używa zamiast tego środowiska IWebHostEnvironment
Mark Schultheiss