วิธีรับสภาพแวดล้อมการพัฒนา / การจัดเตรียม / การผลิตใน 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 แทน
Mark Schultheiss

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 หลักอธิบายถึงวิธีการที่จะบรรลุนี้ ใช้ตัวแปรสภาพแวดล้อมที่เรียกASPNETCORE_ENVIRONMENTว่าถูกตั้งค่าเป็นสภาพแวดล้อมที่คุณต้องการจากนั้นคุณมีสองตัวเลือก

ตรวจสอบชื่อสภาพแวดล้อม

จากเอกสาร :

IHostingEnvironmentบริการให้นามธรรมหลักสำหรับการทำงานร่วมกับสภาพแวดล้อม บริการนี้มีให้โดยชั้นการโฮสต์ ASP.NET และสามารถแทรกลงในตรรกะการเริ่มต้นของคุณผ่านการฉีดขึ้นอยู่กับ เทมเพลตเว็บไซต์ 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.0แอป MVC / 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/ …
André Morales

นี่คือการเชื่อมโยงภาษาอังกฤษโพสต์โดยAndré: docs.microsoft.com/en-us/aspnet/core/fundamentals/...
Ahong

1
คัดค้าน IHostingEnvironment env ใช้ IWebHostEnvironment env แทน
Mark Schultheiss

21

สามารถทำได้โดยไม่ต้องมีคุณสมบัติพิเศษหรือพารามิเตอร์วิธีเช่น:

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

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

2
คำตอบที่ดีที่สุด ขอบคุณ
Shady Sherif

7
สิ่งนี้จะแสดงคำเตือนต่อไปนี้ใน. NET Core 3.0: การเรียก 'BuildServiceProvider' จากรหัสแอปพลิเคชันจะส่งผลให้มีการสร้างสำเนาของบริการแบบซิงเกิลเพิ่มเติม พิจารณาทางเลือกอื่น ๆ เช่นบริการฉีดพึ่งพาเป็นพารามิเตอร์เพื่อ 'กำหนดค่า'
Eternal21

2
คัดค้าน IHostingEnvironment env ใช้ IWebHostEnvironment env แทน
Mark Schultheiss

19

หากคุณต้องการทดสอบสิ่งนี้ใน codebase ของคุณที่ไม่สามารถเข้าถึง IHostingEnvironment ได้อย่างง่ายดายอีกวิธีหนึ่งในการทำเช่นนี้คือ:

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

ทางสั้น! โปรดทราบว่าชื่อตัวแปรแตกต่างกันระหว่าง "asp.net core" และ "asp.net"
nmDat

15

ต่อเอกสาร

กำหนดค่าและ ConfigureServices สนับสนุนรุ่นเฉพาะของสภาพแวดล้อมของฟอร์มกำหนดค่า {EnvironmentName} และกำหนดค่า {EnvironmentName} บริการ:

คุณสามารถทำอะไรเช่นนี้ ...

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
นี่คือการประชุมที่อร่อยที่สุด
Stuart.Sklinar

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 2. สำหรับ 3 IWebHostEnvironmentรุ่นที่คุณต้องการจะใช้


5

สภาพแวดล้อมการโฮสต์มาจากตัวแปรสภาพแวดล้อม ASPNET_ENV ซึ่งมีให้ในระหว่างการเริ่มต้นใช้วิธีการขยาย IHostingEnvironment.IsEnvironment หรือหนึ่งในวิธีการอำนวยความสะดวกที่สอดคล้องกันของ IsDevelopment หรือ IsProduction บันทึกสิ่งที่คุณต้องการใน Startup () หรือในการเรียกใช้ ConfigureServices:

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

IHostingEnvironmentConfigureServicesไม่สามารถใช้ได้ใน
มูฮัมหมัดเรฮันซาอีด

1
ไม่มันไม่ใช่. กลับไปที่คำตอบของฉันเกี่ยวกับวิธีการจัดการกับมัน
Jeff Dunlop

8
ตอนนี้ตัวแปรสภาพแวดล้อมเป็น "ASPNETCORE_ENVIRONMENT"
Anthony

คัดค้าน IHostingEnvironment env ใช้ IWebHostEnvironment env แทน
Mark Schultheiss

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 Startup-constructor คาดหวังเพียงพารามิเตอร์ 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 แทน
Mark Schultheiss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.