本篇将演示Asp.Net Core如何在多环境下进行开发适配。
在一个正规的开发流程里,软件开发部署将要经过三个阶段:开发、测试、上线,对应了三个环境:开发、测试、生产。在不同的环境里,需要编写不同的代码,比如,在开发环境里,为了方便开发和调试,前段js文件和css文件不会被压缩,异常信息将会暴露得更加明显,缓存一般也不会使用等等。而在测试环境里,为了更加接近生产环境,在开发采取的调试手段将会被屏蔽,同时为了能更好的测试发现问题,通常也会添加一些测试专用的服务和代码。最终在生产环境上,因为高效性、容错和友好性或者安全性等原因,某些功能会被屏蔽,某些功能将会被更加谨慎或者有效的手段代替。在这种情况下,需要能通过某种手段,使一套代码在不同环境下部署时能体现不同的特性。
第一部分、多环境标识
在.Net Core里,通过一个特殊的环境变量: ASPNETCORE_ENVIRONMENT 来标识多环境,默认情况下,会有下面三个值
- Development:开发
- Staging:预发布
- Production:生产
借助不同的开发工具进行调试时,会有不同的配置方式。
在Visual Studio Code里:
在 launch.json 里配置 ASPNETCORE_ENVIRONMENT 的值,这个文件在工程目录下的.vscode目录里,这个目录和里面的文件是在VS Code里开发调试时特有的。
1 { 2 "version": "0.2.0", 3 "configurations": [ 4 { 5 "name": ".NET Core Launch (console)", 6 "type": "coreclr", 7 "request": "launch", 8 "preLaunchTask": "build", 9 "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/WebApiFrame.dll", 10 "args": [], 11 "cwd": "${workspaceRoot}", 12 "stopAtEntry": false, 13 "externalConsole": false, 14 "env": { 15 "ASPNETCORE_ENVIRONMENT": "Development" 16 } 17 }, 18 { 19 "name": ".NET Core Launch (web)", 20 "type": "coreclr", 21 "request": "launch", 22 "preLaunchTask": "build", 23 "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/WebApiFrame.dll", 24 "args": [], 25 "cwd": "${workspaceRoot}", 26 "stopAtEntry": false, 27 "launchBrowser": { 28 "enabled": true, 29 "args": "${auto-detect-url}", 30 "windows": { 31 "command": "cmd.exe", 32 "args": "/C start ${auto-detect-url}" 33 }, 34 "osx": { 35 "command": "open" 36 }, 37 "linux": { 38 "command": "xdg-open" 39 } 40 }, 41 "env": { 42 "ASPNETCORE_ENVIRONMENT": "Development" 43 } 44 }, 45 { 46 "name": ".NET Core Attach", 47 "type": "coreclr", 48 "request": "attach", 49 "processId": 0 50 } 51 ] 52 }
在这个配置文件的configurations节点下有三个json对象,分别对应着三种不同的启动方式,前两个分别对应着控制台启动和Web浏览器启动,最后一个采用附加进程的方式启动。
在前两种方式的配置里都有一个名字叫env的节点,节点里将配置 ASPNETCORE_ENVIRONMENT 的值。当采用这两种的任意一种方式启动时,可以看到控制台里将显示当前程序的环境标识。如果不配置这个环境变量,默认将是Production。
在Visual Studio 2015里:
在 launchSettings.json 里配置 ASPNETCORE_ENVIRONMENT 的值。这个文件在工程目录下的Properties文件夹里。这个文件夹和里面的文件也是在VS2015开发调试时里特有的。
1 { 2 "iisSettings": { 3 "windowsAuthentication": false, 4 "anonymousAuthentication": true, 5 "iisExpress": { 6 "applicationUrl": "http://localhost:11974/", 7 "sslPort": 0 8 } 9 }, 10 "profiles": { 11 "IIS Express": { 12 "commandName": "IISExpress", 13 "launchBrowser": true, 14 "launchUrl": "api/values", 15 "environmentVariables": { 16 "ASPNETCORE_ENVIRONMENT": "Development" 17 } 18 }, 19 "ExampleTest": { 20 "commandName": "Project", 21 "launchBrowser": true, 22 "launchUrl": "http://localhost:5000/", 23 "environmentVariables": { 24 "ASPNETCORE_ENVIRONMENT": "Development" 25 } 26 } 27 } 28 }
同样,这个文件也描述了两种启动调试的方式:IIS宿主启动和控制台启动,每种方式里都有一个environmentVariables节点,节点里将配置 ASPNETCORE_ENVIRONMENT 的值。
另外,在VS2015里也可以通过项目的属性可视化界面进行配置,最终的效果会同步修改 launchSettings.json 文件内容
在cmd窗口控制台里:
当使用cmd窗口进行启动时,可以使用下面的命令进行设置
通过 set 命令设置环境变量 ASPNETCORE_ENVIRONMENT 的值,然后通过 dotnet run 启动。
也可以通过设置当前机器的环境变量。设置好后需要重新打开cmd窗口,将环境变量读取到当前环境里。
第二部分、多环境判断
在.Net Core里,通过 IHostingEnvironment 接口来获取 ASPNETCORE_ENVIRONMENT 变量的相关信息。这个接口通过依赖注入的方式获取对应的实例对象。
1 using System.IO; 2 using Microsoft.AspNetCore.Builder; 3 using Microsoft.AspNetCore.Hosting; 4 using Microsoft.Extensions.Configuration; 5 using Microsoft.Extensions.DependencyInjection; 6 using Microsoft.Extensions.Logging; 7 8 namespace WebApiFrame 9 { 10 public class Startup 11 { 12 public IConfiguration Configuration { get; } 13 14 public Startup(IHostingEnvironment env) 15 { 16 var builder = new ConfigurationBuilder() 17 .SetBasePath(Directory.GetCurrentDirectory()) 18 .AddJsonFile("appsettings.json"); 19 20 Configuration = builder.Build(); 21 22 System.Console.WriteLine($"Current State: {env.EnvironmentName}"); 23 System.Console.WriteLine($"Development State: {env.IsDevelopment()}"); 24 System.Console.WriteLine($"Staging State: {env.IsStaging()}"); 25 System.Console.WriteLine($"Production State: {env.IsProduction()}"); 26 } 27 28 public void ConfigureServices(IServiceCollection services) 29 { 30 services.AddOptions(); 31 services.Configure<ConfigOptions>(Configuration.GetSection("CfgContent")); 32 33 // 注入MVC框架 34 services.AddMvc(); 35 } 36 37 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env) 38 { 39 // 添加日志支持 40 loggerFactory.AddConsole(Configuration.GetSection("Logging")); 41 loggerFactory.AddDebug(); 42 43 // 添加NLog日志支持 44 //loggerFactory.AddNLog(); 45 46 // 添加MVC中间件 47 app.UseMvc(); 48 } 49 } 50 }
上面的代码在VS Code里调试时控制台输出的效果如下
在 Startup.cs 类里, IHostingEnvironment 接口可以作为构造函数和Configure方法的参数,通过依赖注入的方式获取实例。
通过实例的EnvironmentName属性可以获取到 ASPNETCORE_ENVIRONMENT 环境变量的值,同时也可以通过IsDevelopment、IsStaging和IsProduction方法快速判断属性值。
另外,也可以通过以下另外一种方式根据 ASPNETCORE_ENVIRONMENT 环境变量的值执行不同的代码
1 using System.IO; 2 using Microsoft.AspNetCore.Builder; 3 using Microsoft.AspNetCore.Hosting; 4 using Microsoft.AspNetCore.Http; 5 using Microsoft.Extensions.Configuration; 6 using Microsoft.Extensions.DependencyInjection; 7 using Microsoft.Extensions.Logging; 8 9 namespace WebApiFrame 10 { 11 public class Startup 12 { 13 public IConfiguration Configuration { get; } 14 15 public Startup(IHostingEnvironment env) 16 { 17 var builder = new ConfigurationBuilder() 18 .SetBasePath(Directory.GetCurrentDirectory()) 19 .AddJsonFile("appsettings.json"); 20 21 Configuration = builder.Build(); 22 23 System.Console.WriteLine($"Current State: {env.EnvironmentName}"); 24 } 25 26 // Development环境下执行的ConfigureServices方法 27 public void ConfigureDevelopmentServices(IServiceCollection services) 28 { 29 System.Console.WriteLine($"ConfigureDevelopmentServices Excuted."); 30 } 31 32 // Development环境下执行的Configure方法 33 public void ConfigureDevelopment(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env) 34 { 35 app.Run(async context => 36 { 37 await context.Response.WriteAsync("ConfigureDevelopment Excuted."); 38 }); 39 } 40 41 public void ConfigureServices(IServiceCollection services) 42 { 43 services.AddOptions(); 44 services.Configure<ConfigOptions>(Configuration.GetSection("CfgContent")); 45 46 // 注入MVC框架 47 services.AddMvc(); 48 } 49 50 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env) 51 { 52 // 添加日志支持 53 loggerFactory.AddConsole(Configuration.GetSection("Logging")); 54 loggerFactory.AddDebug(); 55 56 // 添加NLog日志支持 57 //loggerFactory.AddNLog(); 58 59 // 添加MVC中间件 60 app.UseMvc(); 61 } 62 } 63 }
启动调试,访问地址 http://localhost:5000/ ,查看控制台日志和页面内容
可以看到,通过特殊方法名 Configure{ASPNETCORE_ENVIRONMENT}Services 和 Configure{ASPNETCORE_ENVIRONMENT} 可以在不同的环境变量下执行不同的代码。