Cara mendapatkan Lingkungan Pengembangan / Pementasan / produksi Hosting di ConfigureServices

171

Bagaimana saya mendapatkan Lingkungan Hosting Pengembangan / Pementasan / produksi dalam ConfigureServicesmetode di Startup?

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

The ConfigureServicesMetode hanya membutuhkan satu IServiceCollectionparameter.

Muhammad Rehan Saeed
sumber
4
mengapa tidak IHostingEnvironmentbisa disuntikkan ke ConfigureServices saja? kelalaian? atau alasan yang perlu kita waspadai?
Simon_Weaver

Jawaban:

226

Anda dapat dengan mudah mengaksesnya di ConfigureServices, tetap saja ke properti selama metode Startup yang disebut pertama dan mendapatkannya diteruskan, kemudian Anda dapat mengakses properti dari 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
sumber
13
Per dokumen , metode ini tidak boleh digunakan. Anda seharusnya menggunakan CurrentEnvironment.IsEnvironment("environmentname").
vaindil
28
atau CurrentEnvironment.IsDevelopment()/CurrentEnvironment.IsProduction()
Simon_Weaver
3
@ vaindil - dokumen yang Anda referensi tidak mengatakan metode ini tidak boleh digunakan. Contoh Anda hanya mengabaikan casing, yang lebih disukai dalam banyak kasus tetapi bukan perintah
Coruscate5
3
@ Coruscate5 Oke, itu tidak secara eksplisit mengatakan TIDAK menggunakan metode ini, tetapi mengatakan untuk menggunakan metode lain BUKAN. Itu hal yang hampir sama.
vaindil
8
IHostingEnvironment env yang sudah usang menggunakan IWebHostEnvironment env sebagai gantinya
Mark Schultheiss
56

TL; DR

Setel variabel lingkungan yang dipanggil ASPNETCORE_ENVIRONMENTdengan nama lingkungan (misalnya Production). Kemudian lakukan satu dari dua hal:

  • Inject IHostingEnvironmentke Startup.cs, kemudian menggunakan ( envdi sini) untuk memeriksa: env.IsEnvironment("Production"). Jangan periksa menggunakan env.EnvironmentName == "Production"!
  • Gunakan Startupkelas yang terpisah atau individu Configure/ ConfigureServicesfungsi. Jika suatu kelas atau fungsi cocok dengan format ini, mereka akan digunakan sebagai ganti dari opsi standar pada lingkungan itu.
    • Startup{EnvironmentName}() (seluruh kelas) || contoh:StartupProduction()
    • Configure{EnvironmentName}()|| contoh:ConfigureProduction()
    • Configure{EnvironmentName}Services()|| contoh:ConfigureProductionServices()

Penjelasan lengkap

.NET Core docs menjelaskan cara melakukannya . Gunakan variabel lingkungan bernama ASPNETCORE_ENVIRONMENTyang diatur ke lingkungan yang Anda inginkan, maka Anda memiliki dua pilihan.

Periksa nama lingkungan

Dari dokumen :

The IHostingEnvironmentlayanan menyediakan abstraksi inti untuk bekerja dengan lingkungan. Layanan ini disediakan oleh lapisan hosting ASP.NET, dan dapat disuntikkan ke logika startup Anda melalui Dependency Injection. Templat situs web ASP.NET Core di Visual Studio menggunakan pendekatan ini untuk memuat file konfigurasi khusus lingkungan (jika ada) dan untuk menyesuaikan pengaturan penanganan kesalahan aplikasi. Dalam kedua kasus, perilaku ini dicapai dengan merujuk ke lingkungan yang ditentukan saat ini dengan memanggil EnvironmentNameatau IsEnvironmentpada saat IHostingEnvironmentditeruskan ke metode yang sesuai.

CATATAN: Memeriksa nilai sebenarnya dari env.EnvironmentNameyang tidak dianjurkan!

Jika Anda perlu memeriksa apakah aplikasi berjalan di lingkungan tertentu, gunakan env.IsEnvironment("environmentname")karena itu akan mengabaikan case dengan benar (alih-alih memeriksa jika env.EnvironmentName == "Development"misalnya).

Gunakan kelas yang terpisah

Dari dokumen :

Ketika aplikasi ASP.NET Core dimulai, Startupkelas digunakan untuk mem-bootstrap aplikasi, memuat pengaturan konfigurasinya, dll. ( Pelajari lebih lanjut tentang startup ASP.NET ). Namun, jika kelas ada bernama Startup{EnvironmentName}(misalnya StartupDevelopment), dan ASPNETCORE_ENVIRONMENTvariabel lingkungan cocok dengan nama itu, maka Startupkelas itu yang digunakan. Dengan demikian, Anda dapat mengkonfigurasi Startupuntuk pengembangan, tetapi memiliki terpisah StartupProductionyang akan digunakan ketika aplikasi dijalankan dalam produksi. Atau sebaliknya.

Selain menggunakan Startupkelas yang sepenuhnya terpisah berdasarkan lingkungan saat ini, Anda juga dapat membuat penyesuaian bagaimana aplikasi dikonfigurasi dalam Startupkelas. Metode Configure()dan ConfigureServices()mendukung versi khusus lingkungan yang mirip dengan Startupkelas itu sendiri, dari bentuk Configure{EnvironmentName}()dan Configure{EnvironmentName}Services(). Jika Anda mendefinisikan metode, ConfigureDevelopment()itu akan dipanggil alih-alih Configure()ketika lingkungan diatur ke pengembangan. Demikian juga, ConfigureDevelopmentServices()akan dipanggil bukannya ConfigureServices()di lingkungan yang sama.

vaindil
sumber
29

Di .NET Core 2.0aplikasi MVC / Microsoft.AspNetCore.Allv2.0.0, Anda dapat memiliki kelas startup khusus lingkungan seperti yang dijelaskan oleh @vaindil tapi saya tidak suka pendekatan itu.

Anda juga dapat menyuntikkan IHostingEnvironmentke StartUpkonstruktor. Anda tidak perlu menyimpan variabel lingkungan di Programkelas.

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
sumber
1
Detail dapat dilihat di: docs.microsoft.com/pt-br/aspnet/core/fundamentals/…
André Morales
Berikut ini adalah tautan bahasa Inggris yang diposting oleh André: docs.microsoft.com/en-us/aspnet/core/fundamentals/…
ahong
1
IHostingEnvironment env usang menggunakan IWebHostEnvironment env sebagai gantinya
Mark Schultheiss
21

Ini dapat dilakukan tanpa parameter properti atau metode tambahan, seperti:

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

    if (env.IsProduction()) DoSomethingDifferentHere();
}
edicius6
sumber
2
jawaban terbaik yang pernah ada. thanx
Shady Sherif
7
Ini melempar peringatan berikut di .NET Core 3.0: Memanggil 'BuildServiceProvider' dari kode aplikasi menghasilkan salinan tambahan layanan singleton yang dibuat. Pertimbangkan alternatif seperti layanan injeksi ketergantungan sebagai parameter untuk 'Konfigurasi'.
Eternal21
2
IHostingEnvironment env usang menggunakan IWebHostEnvironment env sebagai gantinya
Mark Schultheiss
19

Jika Anda perlu menguji ini di suatu tempat di basis kode Anda yang tidak memiliki akses mudah ke IHostingEnvironment, cara lain yang mudah untuk melakukannya adalah seperti ini:

bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
Patrick
sumber
baik, jalan pendek! Perlu diingat nama variabelnya berbeda antara "asp.net core" dan "asp.net"
nmDat
15

per dokumen

Konfigurasikan dan ConfigureServices mendukung versi khusus lingkungan dari formulir Configure {EnvironmentName} dan Configure {EnvironmentName} Layanan:

Anda dapat melakukan sesuatu seperti ini ...

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
}
Sepatu
sumber
1
Ini adalah konvensi terbaik
Stuart.Sklinar
11

Saya ingin mendapatkan lingkungan di salah satu layanan saya. Ini sangat mudah dilakukan! Saya hanya menyuntikkannya ke konstruktor seperti ini:

    private readonly IHostingEnvironment _hostingEnvironment;

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

Sekarang nanti dalam kode saya bisa melakukan ini:

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

EDIT:

Kode di atas adalah untuk .NET Core 2. Untuk versi 3 Anda ingin menggunakannya IWebHostEnvironment.

Jess
sumber
5

Lingkungan hosting berasal dari variabel lingkungan ASPNET_ENV, yang tersedia selama Startup menggunakan metode ekstensi IHostingEnvironment.IsEnvironment, atau salah satu metode kenyamanan yang sesuai dari IsDevelopment atau IsProduction. Simpan apa yang Anda butuhkan di Startup (), atau di panggilan ConfigureServices:

var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");
Jeff Dunlop
sumber
IHostingEnvironmenttidak tersedia di ConfigureServices.
Muhammad Rehan Saeed
1
Tidak, tidak. Lihat kembali jawaban saya tentang cara menghadapinya.
Jeff Dunlop
8
Variabel lingkungan sekarang "ASPNETCORE_ENVIRONMENT"
Anthony
IHostingEnvironment env usang menggunakan IWebHostEnvironment env sebagai gantinya
Mark Schultheiss
5

Hanya untuk berjaga-jaga jika ada yang melihat ini juga. Di .net core 3+ sebagian besar sudah usang. Cara pembaruan adalah:

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

Di Dotnet Core 2.0, Startup-constructor hanya mengharapkan parameter-konfigurasi IC.

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

Bagaimana cara membaca lingkungan hosting di sana? Saya menyimpannya di kelas Program selama ConfigureAppConfiguration (gunakan BuildWebHost penuh alih-alih 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();
    }

Semut kemudian membacanya di ConfigureServices seperti ini:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}
toralux
sumber
IHostingEnvironment env usang menggunakan IWebHostEnvironment env sebagai gantinya
Mark Schultheiss