Cách nhận Môi trường Lưu trữ / Phát triển / Sản xuất trong Cấu hình Dịch vụ


170

Làm cách nào để có được Môi trường Hosting Phát triển / Dàn dựng / Sản xuất trong ConfigureServicesphương thức Khởi động?

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

Các ConfigureServicesphương pháp duy nhất có một đơn IServiceCollectiontham số.


4
Tại sao không IHostingEnvironmentthể được đưa vào ConfigureService? giám sát? hoặc một lý do chúng ta cần phải nhận thức?
Simon_Weaver

Câu trả lời:


225

Bạn có thể dễ dàng truy cập nó trong ConfigureService, chỉ cần duy trì nó đến một thuộc tính trong phương thức Khởi động được gọi trước và được truyền vào, sau đó bạn có thể truy cập thuộc tính từ ConfigureService.

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
Theo các tài liệu , phương pháp này không nên được sử dụng. Thay vào đó bạn nên sử dụng CurrentEnvironment.IsEnvironment("environmentname").
vaindil

28
hoặc CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver

3
@vaindil - tài liệu bạn tham khảo không nói phương pháp này không nên được sử dụng. Ví dụ của bạn chỉ đơn giản là bỏ qua vỏ bọc, tốt hơn trong nhiều trường hợp nhưng không phải là một điều răn
Coruscate5

3
@ Coruscate5 Được rồi, nó không nói rõ ràng là KHÔNG sử dụng phương pháp này, nhưng nó nói sử dụng phương pháp khác INSTEAD. Đó hầu như là điều tương tự.
vaindil

8
thay thế IhostingEn Môi trường env sử dụng IWebhostEn Môi trường env thay thế
Mark Schultheiss

56

TL; DR

Đặt một biến môi trường được gọi ASPNETCORE_ENVIRONMENTvới tên của môi trường (ví dụ Production). Sau đó, làm một trong hai điều:

  • Tiêm IHostingEnvironmentvào Startup.cs, sau đó sử dụng ( envở đây) để kiểm tra : env.IsEnvironment("Production"). Đừng kiểm tra bằng cách sử dụng env.EnvironmentName == "Production"!
  • Sử dụng Startupcác lớp riêng biệt hoặc cá nhân Configure/ ConfigureServiceschức năng. Nếu một lớp hoặc các hàm khớp với các định dạng này, chúng sẽ được sử dụng thay vì các tùy chọn tiêu chuẩn trên môi trường đó.
    • Startup{EnvironmentName}() (cả lớp) || thí dụ:StartupProduction()
    • Configure{EnvironmentName}()| | thí dụ:ConfigureProduction()
    • Configure{EnvironmentName}Services()| | thí dụ:ConfigureProductionServices()

Giải thích đầy đủ

Các tài liệu .NET Core mô tả cách thực hiện điều này . Sử dụng một biến môi trường được gọi là biến được ASPNETCORE_ENVIRONMENTđặt thành môi trường bạn muốn, sau đó bạn có hai lựa chọn.

Kiểm tra tên môi trường

Từ các tài liệu :

Các IHostingEnvironmentdịch vụ cung cấp trừu tượng cốt lõi để làm việc với môi trường. Dịch vụ này được cung cấp bởi lớp lưu trữ ASP.NET và có thể được đưa vào logic khởi động của bạn thông qua Dependency Injection. Mẫu trang web ASP.NET Core trong Visual Studio sử dụng phương pháp này để tải các tệp cấu hình dành riêng cho môi trường (nếu có) và để tùy chỉnh các cài đặt xử lý lỗi của ứng dụng. Trong cả hai trường hợp, hành vi này đạt được bằng cách tham khảo môi trường hiện được chỉ định bằng cách gọi EnvironmentNamehoặc IsEnvironmenttheo trường hợp IHostingEnvironmentđược truyền vào phương thức thích hợp.

Chú ý: Kiểm tra giá trị thực tế env.EnvironmentNamekhông khuyến khích!

Nếu bạn cần kiểm tra xem ứng dụng có chạy trong một môi trường cụ thể hay không, hãy sử dụng env.IsEnvironment("environmentname")vì nó sẽ bỏ qua trường hợp chính xác (thay vì kiểm tra nếu env.EnvironmentName == "Development"chẳng hạn).

Sử dụng các lớp riêng biệt

Từ các tài liệu :

Khi một ứng dụng ASP.NET Core khởi động, Startuplớp được sử dụng để khởi động lại ứng dụng, tải các cài đặt cấu hình của nó, v.v. ( tìm hiểu thêm về khởi động ASP.NET ). Tuy nhiên, nếu một lớp tồn tại được đặt tên Startup{EnvironmentName}(ví dụ StartupDevelopment) và ASPNETCORE_ENVIRONMENTbiến môi trường khớp với tên đó, thì Startuplớp đó được sử dụng thay thế. Do đó, bạn có thể định cấu hình Startupđể phát triển, nhưng có một phần riêng biệt StartupProductionsẽ được sử dụng khi ứng dụng được chạy trong sản xuất. Hoặc ngược lại.

Ngoài việc sử dụng một Startuplớp hoàn toàn riêng biệt dựa trên môi trường hiện tại, bạn cũng có thể điều chỉnh cách ứng dụng được cấu hình trong một Startuplớp. Các phương thức Configure()ConfigureServices()hỗ trợ các phiên bản dành riêng cho môi trường tương tự như Startupchính lớp, của biểu mẫu Configure{EnvironmentName}()Configure{EnvironmentName}Services(). Nếu bạn định nghĩa một phương thức, ConfigureDevelopment()nó sẽ được gọi thay vì Configure()khi môi trường được đặt thành phát triển. Tương tự như vậy, ConfigureDevelopmentServices()sẽ được gọi thay vì ConfigureServices()trong cùng một môi trường.


29

Trong .NET Core 2.0ứng dụng MVC / Microsoft.AspNetCore.Allv2.0.0, bạn có thể có lớp khởi động cụ thể về môi trường như được mô tả bởi @vaindil nhưng tôi không thích cách tiếp cận đó.

Bạn cũng có thể tiêm IHostingEnvironmentvào StartUpconstructor. Bạn không cần lưu trữ biến môi trường trong Programlớp.

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

        ......
    }
}


Đây là đường dẫn tiếng Anh được đăng bởi André: docs.microsoft.com/en-us/aspnet/core/fundamentals/ Kẻ
ahong

1
thay thế IhostingEn Môi trường env sử dụng IWebhostEn Môi trường env thay thế
Đánh dấu Schultheiss

21

Điều này có thể được thực hiện mà không có bất kỳ thuộc tính hoặc tham số phương thức bổ sung nào, như vậy:

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

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

2
câu trả lời tốt nhất thanx
Shady Sherif

7
Điều này đưa ra cảnh báo sau trong .NET Core 3.0: Gọi 'BuildServiceProvider' từ mã ứng dụng dẫn đến một bản sao bổ sung của các dịch vụ đơn lẻ được tạo. Xem xét các lựa chọn thay thế, chẳng hạn như dịch vụ tiêm phụ thuộc làm tham số cho 'Định cấu hình'.
Eternal21

2
thay thế IhostingEn Môi trường env sử dụng IWebhostEn Môi trường env thay thế
Đánh dấu Schultheiss

19

Nếu bạn cần kiểm tra điều này ở đâu đó trong cơ sở mã của bạn mà không có quyền truy cập dễ dàng vào IhostingEn Môi trường, một cách dễ dàng khác để làm điều đó là như sau:

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

tốt, con đường ngắn! Hãy ghi nhớ tên biến khác nhau giữa "asp.net core" và "asp.net"
nmDat

14

theo các tài liệu

Cấu hình và ConfigureService hỗ trợ các phiên bản cụ thể cho môi trường của biểu mẫu Cấu hình {Môi trường Tên} và Cấu hình Dịch vụ {Môi trường Tên}:

Bạn có thể làm một cái gì đó như thế này ...

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
}

Đây là hội nghị đẹp nhất
Stuart.Sklinar

11

Tôi muốn có được môi trường trong một trong các dịch vụ của tôi. Nó thực sự dễ dàng để làm! Tôi chỉ tiêm nó cho các nhà xây dựng như thế này:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Bây giờ sau này trong mã tôi có thể làm điều này:

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

BIÊN TẬP:

Mã ở trên là dành cho .NET Core 2. Đối với phiên bản 3 bạn sẽ muốn sử dụng IWebHostEnvironment.


5

Môi trường lưu trữ xuất phát từ biến môi trường ASPNET_ENV, có sẵn trong khi khởi động bằng cách sử dụng phương thức mở rộng IhostingEn môi.IsEn Môi trường hoặc một trong các phương thức tiện lợi tương ứng của IsDevelopment hoặc Is sản xuất. Lưu những gì bạn cần trong Startup () hoặc trong cuộc gọi ConfigureService:

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

IHostingEnvironmentkhông có sẵn trong ConfigureServices.
Muhammad Rehan Saeed

1
Không, không phải vậy. Tham khảo lại câu trả lời của tôi về cách đối phó với nó.
Jeff Dunlop

8
Biến môi trường bây giờ là "ASPNETCORE_ENVIRONMENT"
Anthony

thay thế IhostingEn Môi trường env sử dụng IWebhostEn Môi trường env thay thế
Mark Schultheiss

5

Chỉ trong trường hợp ai đó đang tìm kiếm điều này quá. Trong lõi .net 3+ hầu hết điều này đã lỗi thời. Cách cập nhật là:

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

2

Trong Dotnet Core 2.0, Startup-constructor chỉ mong đợi một tham số IConfiguration.

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

Làm thế nào để đọc môi trường lưu trữ ở đó? Tôi lưu trữ nó trong lớp Chương trình trong ConfigureAppConfiguration (sử dụng BuildWebhost đầy đủ thay vì 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 sau đó đọc nó trong ConfigureService như thế này:

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

NỮA IHostingEnvironment env sử dụng IWebHostEnvironment ENV thay
Đánh dấu Schultheiss
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.