Як отримати середовище хостингу для розробки / інсценізації / виробництва в ConfigureServices


171

Як отримати середовище розробки / інсценізації / виробництва хостингу ConfigureServicesметодом у запуску?

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

ConfigureServicesМетод тільки приймає один IServiceCollectionпараметр.


4
чому не можна IHostingEnvironmentпросто вводити в ConfigureServices? нагляд? чи причину, про яку нам потрібно знати?
Simon_Weaver

Відповіді:


225

Ви можете легко отримати доступ до нього в ConfigureServices, просто збережіть його у властивості під час методу запуску, який викликається спочатку і передає його в дію, потім ви можете отримати доступ до властивості з 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
Згідно з документами , цей метод не слід застосовувати. Натомість ви повинні використовувати CurrentEnvironment.IsEnvironment("environmentname").
vaindil

28
або CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver

3
@vaindil - документи, на які ви посилаєтесь, не кажуть, що цей метод не слід використовувати. Ваш приклад просто ігнорує кожух, який є переважним у багатьох випадках, але не є заповіддю
Coruscate5

3
@ Coruscate5 Гаразд, він прямо не говорить НЕ використовувати цей метод, але говорить, щоб використовувати інший метод ВСТАНОВИТИ. Це практично те саме.
vaindil

8
застарілий IHostingEnvironment env замість цього використовується IWebHostEnvironment env
Марк Шультхейс

56

TL; DR

Встановіть змінну оточення, яку називають ASPNETCORE_ENVIRONMENTіменем середовища (наприклад Production). Потім виконайте одну з двох речей:

  • Вводять IHostingEnvironmentв Startup.cs, а потім використовувати що ( envтут) , щоб перевірити: env.IsEnvironment("Production"). Не перевіряйте використання env.EnvironmentName == "Production"!
  • Використовуйте або окремі Startupкласи, або окремі Configure/ ConfigureServicesфункції. Якщо клас або функції відповідають цим форматам, вони будуть використовуватися замість стандартних параметрів у цьому середовищі.
    • Startup{EnvironmentName}() (весь клас) || приклад:StartupProduction()
    • Configure{EnvironmentName}()|| приклад:ConfigureProduction()
    • Configure{EnvironmentName}Services()|| приклад:ConfigureProductionServices()

Повне пояснення

Документи .NET Core описують, як це досягти . Використовуйте змінну середовища, яку називають ASPNETCORE_ENVIRONMENTпотрібною середовищем, тоді у вас є два варіанти.

Перевірте назву середовища

З документів :

IHostingEnvironmentСлужба надає базову абстракцію для роботи із середовищами. Ця послуга надається хостинговим шаром ASP.NET і може бути введена у вашу логіку запуску за допомогою Dependency Injection. Шаблон веб-сайту ASP.NET Core у Visual Studio використовує цей підхід для завантаження конфігураційних файлів, що стосуються середовища (якщо вони є) та для налаштування параметрів обробки помилок програми. В обох випадках така поведінка досягається шляхом посилання на вказане в даний час середовище за допомогою виклику EnvironmentNameабо IsEnvironmentза інстанцією IHostingEnvironmentпереходу до відповідного методу.

ПРИМІТКА: Перевірка фактичного значення env.EnvironmentNameє НЕ рекомендується!

Якщо вам потрібно перевірити, чи працює програма у певному середовищі, використовуйте, env.IsEnvironment("environmentname")оскільки вона правильно ігнорує випадок (замість того, щоб перевіряти, чи є це env.EnvironmentName == "Development"наприклад).

Використовуйте окремі класи

З документів :

Коли програма ASP.NET Core запускається, Startupклас використовується для завантаження програми, завантаження її параметрів конфігурації тощо ( дізнайтеся більше про запуск ASP.NET ). Однак якщо клас існує з назвою Startup{EnvironmentName}(наприклад StartupDevelopment), а ASPNETCORE_ENVIRONMENTзмінна середовища відповідає цьому імені, тоді цей Startupклас використовується замість цього. Таким чином, ви можете налаштувати Startupрозробку, але мати окремий, StartupProductionякий би використовувався під час запуску програми у виробництві. Або навпаки.

На додаток до використання абсолютно окремого Startupкласу, що базується на поточному середовищі, ви також можете вносити корективи в налаштування програми у межах Startupкласу. Методи Configure()та ConfigureServices()методи підтримують специфічні для середовища версії, подібні до самого Startupкласу, форми Configure{EnvironmentName}()та Configure{EnvironmentName}Services(). Якщо ви визначите метод, ConfigureDevelopment()він буде викликаний замість того, Configure()коли середовище буде налаштовано на розвиток. Так само ConfigureDevelopmentServices()називали б замість ConfigureServices()того самого середовища.


29

У програмі .NET Core 2.0MVC / Microsoft.AspNetCore.Allv2.0.0 ви можете мати специфічний екологічний клас запуску, як описано у @vaindil, але мені не подобається такий підхід.

Ви також можете вводити IHostingEnvironmentв StartUpконструктор. Вам не потрібно зберігати змінну середовища в Programкласі.

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

        ......
    }
}

1
Деталі можна переглянути в: docs.microsoft.com/pt-br/aspnet/core/fundamentals/…
Андре Моралес

Ось англійська посилання, опублікована Андре: docs.microsoft.com/en-us/aspnet/core/fundamentals/…
ahong

1
застарілий IHostingEnvironment env замість цього використовується IWebHostEnvironment env
Марк Шультхейс

21

Це можна досягти без додаткових властивостей чи параметрів методу, наприклад:

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

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

2
найкраща відповідь коли-небудь. thanx
Shady Sherif

7
Це кидає таке. Попередження у .NET Core 3.0: Виклик "BuildServiceProvider" з коду програми призводить до створення додаткової копії однотонних служб. Розгляньте альтернативи, такі як послуги, які вводять залежність, як параметри "Налаштувати".
Вічний21

2
застарілий IHostingEnvironment env замість цього використовується IWebHostEnvironment env
Марк Шультхейс

19

Якщо вам потрібно перевірити це десь у вашій кодовій базі, що не має простого доступу до IHostingEnvironment, ще один простий спосіб зробити це такий:

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

ну короткий шлях! Пам’ятайте, що назва змінної відрізняється між "ядром asp.net" та "asp.net"
nmDat

15

за док

Налаштування та налаштуванняServices підтримують конкретні версії середовища щодо форми Налаштування {EnvironmentName} та Configure {EnvironmentName} Services:

Ви можете зробити щось подібне ...

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
}

1
Це найприємніша
умова

11

Я хотів отримати середовище в одній зі своїх служб. Це зробити дуже просто! Я просто ввожу це в конструктор так:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Тепер пізніше в коді я можу це зробити:

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

Редагувати:

Код, наведений вище, призначений для .NET Core 2. Для версії 3 ви хочете використовувати IWebHostEnvironment.


5

Середовище хостингу походить із змінної середовища ASPNET_ENV, яка доступна під час запуску за допомогою методу розширення IHostingEnvironment.IsEnvironment або одного з відповідних зручних методів IsDevelopment або IsProduction. Або збережіть те, що вам потрібно в Startup (), або у виклику ConfigureServices:

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

IHostingEnvironmentнедоступний у ConfigureServices.
Мухаммед Рехан Саїд

1
Ні це не так. Зверніться до моєї відповіді про те, як з цим боротися.
Джефф Данлоп

8
Змінна середовища тепер "ASPNETCORE_ENVIRONMENT"
Ентоні

застарілий IHostingEnvironment env замість цього використовується IWebHostEnvironment env
Марк Шультхейс

5

На всякий випадок, коли хтось теж на це звернеться. У .net core 3+ більшість цього є застарілим. Спосіб оновлення:

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

2

У Dotnet Core 2.0 запуск-конструктор очікує лише параметр IConfiguration.

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

Як читати хостинг-середовище там? Я зберігаю його в програмному класі під час ConfigureAppConfiguration (використовуйте повний BuildWebHost замість 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 читає його в ConfigureServices так:

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

застарілий IHostingEnvironment env замість цього використовується IWebHostEnvironment env
Марк Шультхейс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.