c# - introducción - asp.net core vs asp.net mvc
Cómo obtener el entorno de alojamiento de desarrollo/preparación/producción en ConfigureServices (9)
¿Cómo obtengo el entorno de alojamiento de desarrollo / preparación / producción en el método
ConfigureServices
en el inicio?
public void ConfigureServices(IServiceCollection services)
{
// Which environment are we running under?
}
El método
ConfigureServices
solo toma un único parámetro
IServiceCollection
.
TL; DR
Establezca una variable de entorno llamada
ASPNETCORE_ENVIRONMENT
con el nombre del entorno (por ejemplo,
Production
).
Luego haz una de dos cosas:
-
Inyecte
IHostingEnvironment
enStartup.cs
, luego use eso (env
aquí) para verificar:env.IsEnvironment("Production")
. ¡No verifique usandoenv.EnvironmentName == "Production"
! -
Utilice clases de
Startup
separadas o funciones individualesConfigure
/ConfigureServices
. Si una clase o las funciones coinciden con estos formatos, se utilizarán en lugar de las opciones estándar en ese entorno.-
Startup{EnvironmentName}()
(clase completa) || ejemplo:StartupProduction()
-
Configure{EnvironmentName}()
|| ejemplo:ConfigureProduction()
-
Configure{EnvironmentName}Services()
|| ejemplo:ConfigureProductionServices()
-
Explicación completa
Los documentos de .NET Core
describen cómo lograr esto
.
Utilice una variable de entorno llamada
ASPNETCORE_ENVIRONMENT
que esté configurada en el entorno que desee, entonces tiene dos opciones.
Comprobar nombre del entorno
El servicio
IHostingEnvironment
proporciona la abstracción central para trabajar con entornos. Este servicio es proporcionado por la capa de alojamiento ASP.NET y puede inyectarse en su lógica de inicio a través de Inyección de dependencias. La plantilla del sitio web ASP.NET Core en Visual Studio utiliza este enfoque para cargar archivos de configuración específicos del entorno (si están presentes) y para personalizar la configuración de manejo de errores de la aplicación. En ambos casos, este comportamiento se logra haciendo referencia al entorno especificado actualmente llamando aEnvironmentName
oIsEnvironment
en la instancia deIHostingEnvironment
pasa al método apropiado.
NOTA:
env.EnvironmentName
No se
recomienda verificar el valor real de
env.EnvironmentName
!
Si necesita verificar si la aplicación se está ejecutando en un entorno en particular, use
env.IsEnvironment("environmentname")
ya que ignorará correctamente las mayúsculas y minúsculas (en lugar de verificar sienv.EnvironmentName == "Development"
por ejemplo).
Usa clases separadas
Cuando se inicia una aplicación ASP.NET Core, la clase
Startup
se usa para iniciar la aplicación, cargar su configuración, etc. ( obtenga más información sobre el inicio de ASP.NET ). Sin embargo, si existe una clase llamadaStartup{EnvironmentName}
(por ejemploStartupDevelopment
), y la variable de entornoASPNETCORE_ENVIRONMENT
coincide con ese nombre, entonces esa clase deStartup
se usa en su lugar. Por lo tanto, puede configurarStartup
para el desarrollo, pero tener unaStartupProduction
separada que se usaría cuando la aplicación se ejecute en producción. O viceversa.Además de utilizar una clase de
Startup
completamente separada basada en el entorno actual, también puede realizar ajustes en la configuración de la aplicación dentro de una clase deStartup
. Los métodosConfigure()
yConfigureServices()
admiten versiones específicas del entorno similares a la claseStartup
sí, de la formaConfigure{EnvironmentName}()
yConfigure{EnvironmentName}Services()
. Si define un métodoConfigureDevelopment()
, se llamará en lugar deConfigure()
cuando el entorno esté configurado para el desarrollo. Del mismo modo, se llamaríaConfigureServices()
en lugar deConfigureServices()
en el mismo entorno.
El entorno de alojamiento proviene de la variable de entorno ASPNET_ENV, que está disponible durante el inicio utilizando el método de extensión IHostingEnvironment.IsEnvironment, o uno de los métodos de conveniencia correspondientes de IsDevelopment o IsProduction. Guarde lo que necesita en Startup () o en la llamada ConfigureServices:
var foo = Environment.GetEnvironmentVariable("ASPNET_ENV");
En Dotnet Core 2.0, el constructor de inicio solo espera un parámetro IConfiguration.
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
¿Cómo leer el entorno de alojamiento allí? Lo guardo en Program-class durante ConfigureAppConfiguration (uso BuildWebHost completo en lugar 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 luego lo lee en ConfigureServices así:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var isDevelopment = Program.HostingEnvironment.IsDevelopment();
}
En la aplicación
.NET Core 2.0
MVC /
Microsoft.AspNetCore.All
v2.0.0, puede tener una clase de inicio específica para el medio ambiente como se describe en @vaindil, pero no me gusta ese enfoque.
También puede inyectar
IHostingEnvironment
en el constructor
StartUp
.
No necesita almacenar la variable de entorno en la clase
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());
}
});
......
}
}
Esto se puede lograr sin propiedades adicionales o parámetros de método, como sigue:
public void ConfigureServices(IServiceCollection services)
{
IServiceProvider serviceProvider = services.BuildServiceProvider();
IHostingEnvironment env = serviceProvider.GetService<IHostingEnvironment>();
if (env.IsProduction()) DoSomethingDifferentHere();
}
Quería obtener el medio ambiente en uno de mis servicios. ¡Es realmente facil de hacer! Simplemente lo inyecto al constructor así:
private readonly IHostingEnvironment _hostingEnvironment;
public MyEmailService(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
Ahora más adelante en el código puedo hacer esto:
if (_hostingEnvironment.IsProduction()) {
// really send the email.
}
else {
// send the email to the test queue.
}
Si necesita probar esto en algún lugar de su base de código que no tenga fácil acceso al entorno IHosting, otra forma fácil de hacerlo es así:
bool isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
por los docs.microsoft.com/en-us/aspnet/core/fundamentals/environments
Configure y ConfigureServices admiten versiones específicas del entorno del formulario Configure {EnvironmentName} y Configure {EnvironmentName} Servicios:
Puedes hacer algo como esto ...
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
}
puede acceder fácilmente a él en ConfigureServices, simplemente consérvelo en una propiedad durante el método de Inicio que se llama primero y lo pasa, luego puede acceder a la propiedad desde 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...
}