Comment obtenir l'environnement d'hébergement de développement / de préparation / production dans ConfigureServices

171

Comment obtenir l'environnement d'hébergement de développement / de préparation / production dans la ConfigureServicesméthode de démarrage?

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

La ConfigureServicesméthode ne prend qu'un seul IServiceCollectionparamètre.

Muhammad Rehan Saeed
la source
4
pourquoi ne peut-il pas IHostingEnvironmentêtre simplement injecté dans ConfigureServices? surveillance? ou une raison dont nous devons être conscients?
Simon_Weaver

Réponses:

226

Vous pouvez facilement y accéder dans ConfigureServices, il suffit de le conserver dans une propriété pendant la méthode de démarrage qui est appelée en premier et la fait passer, puis vous pouvez accéder à la propriété à partir de 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
la source
13
Selon la documentation , cette méthode ne doit pas être utilisée. Vous devriez plutôt utiliser CurrentEnvironment.IsEnvironment("environmentname").
vaindil
28
ou CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver
3
@vaindil - les documents auxquels vous faites référence ne disent pas que cette méthode ne doit pas être utilisée. Votre exemple ignore tout simplement l'enveloppe, ce qui est préférable dans de nombreux cas, mais pas un commandement
Coruscate5
3
@ Coruscate5 D'accord, il ne dit pas explicitement de NE PAS utiliser cette méthode, mais il dit d'utiliser l'autre méthode INSTEAD. C'est pratiquement la même chose.
vaindil
8
obsolète IHostingEnvironment env utilise IWebHostEnvironment env à la place
Mark Schultheiss
56

TL; DR

Définissez une variable d'environnement appelée ASPNETCORE_ENVIRONMENTavec le nom de l'environnement (par exemple Production). Ensuite, faites l'une des deux choses suivantes:

  • Injecter IHostingEnvironmentdans Startup.cs, puis utilisez que ( envici) pour vérifier: env.IsEnvironment("Production"). Ne vérifiez pas l' utilisation env.EnvironmentName == "Production"!
  • Utilisez soit séparés Startupclasses ou individuels Configure/ ConfigureServicesfonctions. Si une classe ou les fonctions correspondent à ces formats, elles seront utilisées à la place des options standard de cet environnement.
    • Startup{EnvironmentName}() (classe entière) || exemple:StartupProduction()
    • Configure{EnvironmentName}()|| exemple:ConfigureProduction()
    • Configure{EnvironmentName}Services()|| exemple:ConfigureProductionServices()

Explication complète

La documentation .NET Core décrit comment y parvenir . Utilisez une variable d'environnement appelée ASPNETCORE_ENVIRONMENTqui est définie sur l'environnement souhaité, vous avez alors deux choix.

Vérifier le nom de l'environnement

À partir de la documentation :

Le IHostingEnvironmentservice fournit l'abstraction de base pour travailler avec des environnements. Ce service est fourni par la couche d'hébergement ASP.NET et peut être injecté dans votre logique de démarrage via l'injection de dépendances. Le modèle de site Web ASP.NET Core dans Visual Studio utilise cette approche pour charger les fichiers de configuration spécifiques à l'environnement (le cas échéant) et pour personnaliser les paramètres de gestion des erreurs de l'application. Dans les deux cas, ce comportement est obtenu en faisant référence à l'environnement actuellement spécifié en appelant EnvironmentNameou IsEnvironmentsur l'instance de IHostingEnvironmentpassée à la méthode appropriée.

REMARQUE: ilenv.EnvironmentName n'est pas recommandé de vérifier la valeur réelle de !

Si vous avez besoin de vérifier si l'application s'exécute dans un environnement particulier, utilisez env.IsEnvironment("environmentname")car elle ignorera correctement la casse (au lieu de vérifier si env.EnvironmentName == "Development"par exemple).

Utilisez des classes séparées

À partir de la documentation :

Lorsqu'une application ASP.NET Core démarre, la Startupclasse est utilisée pour amorcer l'application, charger ses paramètres de configuration, etc. (en savoir plus sur le démarrage d'ASP.NET ). Cependant, s'il existe une classe nommée Startup{EnvironmentName}(par exemple StartupDevelopment) et que la ASPNETCORE_ENVIRONMENTvariable d'environnement correspond à ce nom, cette Startupclasse est utilisée à la place. Ainsi, vous pouvez configurer Startuppour le développement, mais en avoir un autre StartupProductionqui serait utilisé lorsque l'application est exécutée en production. Ou vice versa.

En plus d'utiliser une Startupclasse entièrement distincte basée sur l'environnement actuel, vous pouvez également apporter des ajustements à la configuration de l'application dans une Startupclasse. Les méthodes Configure()et ConfigureServices()prennent en charge des versions spécifiques à l'environnement similaires à la Startupclasse elle-même, du formulaire Configure{EnvironmentName}()et Configure{EnvironmentName}Services(). Si vous définissez une méthode, ConfigureDevelopment()elle sera appelée au lieu de Configure()lorsque l'environnement est défini sur développement. De même, ConfigureDevelopmentServices()serait appelé au lieu de ConfigureServices()dans le même environnement.

vaindil
la source
29

Dans .NET Core 2.0MVC app / Microsoft.AspNetCore.Allv2.0.0, vous pouvez avoir une classe de démarrage spécifique à l'environnement comme décrit par @vaindil mais je n'aime pas cette approche.

Vous pouvez également injecter IHostingEnvironmentdans le StartUpconstructeur. Vous n'avez pas besoin de stocker la variable d'environnement dans la 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());
            }            
        });

        ......
    }
}
David Liang
la source
1
Les détails peuvent être consultés dans: docs.microsoft.com/pt-br/aspnet/core/fundamentals
André Morales
Voici le lien en anglais posté par André: docs.microsoft.com/en-us/aspnet/core/fundamentals/…
ahong
1
obsolète IHostingEnvironment env utiliser IWebHostEnvironment env à la place
Mark Schultheiss
21

Cela peut être accompli sans propriétés ou paramètres de méthode supplémentaires, comme ceci:

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

    if (env.IsProduction()) DoSomethingDifferentHere();
}
edicius6
la source
2
la meilleure réponse jamais. thanx
Shady Sherif
7
Cela lève l'avertissement suivant dans .NET Core 3.0: L'appel de «BuildServiceProvider» à partir du code d'application entraîne la création d'une copie supplémentaire des services singleton. Envisagez des alternatives telles que les services d'injection de dépendances comme paramètres à «Configurer».
Eternal21
2
obsolète IHostingEnvironment env utiliser IWebHostEnvironment env à la place
Mark Schultheiss
19

Si vous avez besoin de tester cela quelque part dans votre base de code qui n'a pas un accès facile à IHostingEnvironment, un autre moyen simple de le faire est comme ceci:

bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
Patrick
la source
enfin, à court terme! Gardez à l'esprit que le nom de la variable est différent entre "asp.net core" et "asp.net"
nmDat
15

par les docs

Configurez et ConfigureServices prennent en charge les versions spécifiques à l'environnement du formulaire Configurez {EnvironmentName} et Configurez {EnvironmentName} Services:

Vous pouvez faire quelque chose comme ça ...

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
}
Chaussure
la source
1
C'est la plus belle convention
Stuart.Sklinar
11

Je souhaitais intégrer l'environnement dans l'un de mes services. C'est vraiment facile à faire! Je viens de l'injecter au constructeur comme ceci:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Maintenant, plus tard dans le code, je peux le faire:

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

ÉDITER:

Le code ci-dessus est pour .NET Core 2. Pour la version 3, vous souhaiterez l'utiliser IWebHostEnvironment.

Jess
la source
5

L'environnement d'hébergement provient de la variable d'environnement ASPNET_ENV, qui est disponible au démarrage à l'aide de la méthode d'extension IHostingEnvironment.IsEnvironment, ou de l'une des méthodes de commodité correspondantes d'IsDevelopment ou IsProduction. Enregistrez ce dont vous avez besoin dans Startup () ou dans l'appel ConfigureServices:

var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");
Jeff Dunlop
la source
IHostingEnvironmentn'est pas disponible en ConfigureServices.
Muhammad Rehan Saeed
1
Non ce n'est pas. Reportez-vous à ma réponse pour savoir comment y faire face.
Jeff Dunlop
8
La variable d'environnement est maintenant "ASPNETCORE_ENVIRONMENT"
Anthony
obsolète IHostingEnvironment env utiliser IWebHostEnvironment env à la place
Mark Schultheiss
5

Juste au cas où quelqu'un regarderait ça aussi. Dans .net core 3+, la plupart de ces éléments sont obsolètes. La méthode de mise à jour est:

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

Dans Dotnet Core 2.0, le constructeur de démarrage attend uniquement un paramètre IConfiguration.

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

Comment y lire l'environnement d'hébergement? Je le stocke dans la classe Program pendant ConfigureAppConfiguration (utilisez Full BuildWebHost au lieu 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();
    }

Ant le lit ensuite dans ConfigureServices comme ceci:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}
toralux
la source
obsolète IHostingEnvironment env utiliser IWebHostEnvironment env à la place
Mark Schultheiss