ASP.NET Core 如何设置发布环境
在ASP.NET Core中自带了一些内置对象,可以读取到当前程序处于什么样的环境当中,比如在ASP.NET Core的Startup类的Configure方法中,我们就会看到这么一段代码:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
其中env.IsDevelopment()就可以读出当前程序是否是处于开发环境当中,如果你在Visual Studio中运行ASP.NET Core项目那么上面的env.IsDevelopment()就会返回true,如果你发布(publish)了ASP.NET Core项目,并在IIS中运行发布后的项目代码,那么上面的env.IsDevelopment()就会返回false。
env.IsDevelopment()其实是IHostingEnvironment接口(IHostingEnvironment接口默认就注册在了ASP.NET Core的依赖注入容器中,可以在ASP.NET Core中任何需要用依赖注入的地方<例如,Startup类的构造函数(由于IHostingEnvironment接口默认就在ASP.NET Core的依赖注入容器中,所以在Startup类的构造函数中ASP.NET Core就可以注入IHostingEnvironment接口),Startup类的Configure方法,Controller的构造函数,中间件,MVC视图等地方>使用IHostingEnvironment接口)的一个扩展方法,其定义在HostingEnvironmentExtensions这个扩展类中,可以看到HostingEnvironmentExtensions类定义了一些和ASP.NET Core运行环境相关的方法:
注意在ASP.NET Core 3.0中,HostingEnvironmentExtensions扩展类被HostEnvironmentEnvExtensions扩展类所替代,但是其实大同小异:
其中
- IsDevelopment方法用来检测ASP.NET Core项目当前是否处于开发环境,比如在Visual Studio中运行ASP.NET Core项目IsDevelopment方法就会返回true
- IsProduction方法用来检测ASP.NET Core项目当前是否处于生产环境,比如将ASP.NET Core项目发布(publish)后,IsProduction方法就会返回true
- IsStaging方法用来检测ASP.NET Core项目当前是否处于一个中间环境,比如如果项目还有测试环境,就可以将IsStaging方法用来检测ASP.NET Core项目是否处于测试环境
那么为什么在Visual Studio中运行ASP.NET Core项目,HostingEnvironmentExtensions类的IsDevelopment方法会返回true呢?我们打开ASP.NET Core项目Properties节点下的launchSettings.json文件
其中的Json文本如下:
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52028",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebCoreEnvironments": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
我们可以看到在"profiles"下有一个"IIS Express"节点,其中有一个"ASPNETCORE_ENVIRONMENT"属性,其值为Development,这就表示了当我们在Visual Studio中用IIS Express运行ASP.NET Core项目时,处于的是Development环境,所以此时HostingEnvironmentExtensions类的IsDevelopment方法会返回true。ASPNETCORE_ENVIRONMENT属性后面可以定义任何值,但是一般来说都定义为Development、Production和Staging三个值,对应的HostingEnvironmentExtensions类的三个方法,如果你定义了一个其它的值(比如Staging2),可以用HostingEnvironmentExtensions类的IsEnvironment方法进行检测,参数environmentName就是要检测的环境名(比如Staging2)。当发布ASP.NET Core项目后,ASPNETCORE_ENVIRONMENT属性的默认值会是Production,这就是为什么当ASP.NET Core项目发布后,HostingEnvironmentExtensions类的IsProduction方法会返回true。
此外ASPNETCORE_ENVIRONMENT属性的值还可以影响ASP.NET Core项目appsettings文件的读取,我们来看下面一个例子:
假设我们有个ASP.NET Core MVC项目叫WebCoreEnvironments,其中我们定义了两套appsettings文件:appsettings.Development.json和appsettings.Production.json,分别用于存放项目开发环境和生产环境的参数, appsettings.Development.json和appsettings.Production.json中都定义了一个属性叫TestString,不过两个文件存储的TestString属性值不同。
appsettings.Development.json文件内容如下:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"AppSettings": {
"TestString": "This is development environment"
}
}
appsettings.Production.json文件内容如下:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"AppSettings": {
"TestString": "This is production environment"
}
}
当然可以在默认的appsettings.json文件中也定义TestString属性,当项目中appsettings.Development.json和appsettings.Production.json文件不存在的时候,或当在appsettings.Development.json和appsettings.Production.json文件中找不到TestString属性的时候,就会采用默认的appsettings.json文件的内容。appsettings.json文件内容如下:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AppSettings": {
"TestString": "This is default environment"
},
"AllowedHosts": "*"
}
接着我们在ASP.NET Core MVC项目中定义了一个AppSettings类用于读取和反序列化appsettings文件的内容:
namespace WebCoreEnvironments.Models { public class AppSettings { public string TestString { get; set; } } }
其中就一个TestString属性和appsettings文件中的属性同名。
Startup类的构造函数,从ASP.NET Core 2.0开始,我们可以不修改项目的Startup类构造函数,例如我们也可以采用新建ASP.NET Core 2.0项目时Startup类的默认构造函数:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using WebCoreEnvironments.Models; namespace WebCoreEnvironments { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddOptions(); services.Configure (Configuration.GetSection("AppSettings" )); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
但是我们要修改ASP.NET Core项目中Program类(在ASP.NET Core项目中的Program.cs文件中)的代码如下:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace WebCoreEnvironments { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((webHostBuilderContext, configurationbuilder) => { var env = webHostBuilderContext.HostingEnvironment;//可以通过WebHostBuilderContext类的HostingEnvironment属性得到IHostingEnvironment接口对象 configurationbuilder.SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)//这里采用appsettings.{env.EnvironmentName}.json根据当前的运行环境来加载相应的appsettings文件 .AddEnvironmentVariables(); }) .UseStartup(); } }
可以看到其实我们就是将ASP.NET Core项目Startup类构造函数中配置读取appsettings文件的逻辑,移植到了ASP.NET Core项目中的Program类里面,其中可以通过WebHostBuilderContext类的HostingEnvironment属性得到IHostingEnvironment接口对象,来读取当前ASP.NET Core项目所处的运行环境是什么。
这里在ASP.NET Core 3.0中稍有不同,ASP.NET Core 3.0是通过HostBuilderContext类的HostingEnvironment属性得到IHostEnvironment接口对象,来读取当前ASP.NET Core项目所处的运行环境是什么,ASP.NET Core 3.0的Program类代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace WebCoreEnvironments { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostBuilderContext, configurationbuilder) => { var env = hostBuilderContext.HostingEnvironment;//可以通过HostBuilderContext类的HostingEnvironment属性得到IHostEnvironment接口对象 configurationbuilder.SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)//这里采用appsettings.{env.EnvironmentName}.json根据当前的运行环境来加载相应的appsettings文件 .AddEnvironmentVariables(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } }
ASP.NET Core 3.0
在ASP.NET Core 3.0中,IHostingEnvironment已经过时,请用IWebHostEnvironment接口对象(继承IHostEnvironment接口对象)替换本文所述的IHostingEnvironment接口对象。
详情可以查看:Migrate from ASP.NET Core 2.2 to 3.0
关于本文所述的内容,可以参考微软官方关于ASP.NET Core多环境配置的文档,链接如下:
Use multiple environments in ASP.NET Core
下载本文示例项目代码