咱们先看一下1.x和2.x的程序入口项的一个差别html
public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); } }
public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build(); }
2.x对默认配置进行了简化,把一些基本配置移动了 CreateDefaultBuilder 方法中 json
public static IWebHostBuilder CreateDefaultBuilder(string[] args) { IWebHostBuilder hostBuilder = new WebHostBuilder()
.UseKestrel((Action<WebHostBuilderContext, KestrelServerOptions>) ((builderContext, options) => options.Configure((IConfiguration) builderContext.Configuration.GetSection("Kestrel"))))
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((Action<WebHostBuilderContext, IConfigurationBuilder>) ((hostingContext, config) => { IHostingEnvironment hostingEnvironment = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", true, true); if (hostingEnvironment.IsDevelopment()) { Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName)); if (assembly != (Assembly) null) config.AddUserSecrets(assembly, true); } config.AddEnvironmentVariables(); if (args == null) return; config.AddCommandLine(args); }))
.ConfigureLogging((Action<WebHostBuilderContext, ILoggingBuilder>) ((hostingContext, logging) => { logging.AddConfiguration((IConfiguration) hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); logging.AddDebug(); }))
.ConfigureServices((Action<WebHostBuilderContext, IServiceCollection>) ((hostingContext, services) => { services.PostConfigure<HostFilteringOptions>((Action<HostFilteringOptions>) (options => { if (options.AllowedHosts != null && options.AllowedHosts.Count != 0) return; string str = hostingContext.Configuration["AllowedHosts"]; string[] strArray1; if (str == null) strArray1 = (string[]) null; else strArray1 = str.Split(new char[1]{ ';' }, StringSplitOptions.RemoveEmptyEntries); string[] strArray2 = strArray1; HostFilteringOptions filteringOptions = options; string[] strArray3; if (strArray2 == null || strArray2.Length == 0) strArray3 = new string[1]{ "*" }; else strArray3 = strArray2; filteringOptions.AllowedHosts = (IList<string>) strArray3; })); services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>((IOptionsChangeTokenSource<HostFilteringOptions>) new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration)); services.AddTransient<IStartupFilter, HostFilteringStartupFilter>(); }))
.UseIISIntegration()
.UseDefaultServiceProvider((Action<WebHostBuilderContext, ServiceProviderOptions>) ((context, options) => options.ValidateScopes = context.HostingEnvironment.IsDevelopment())); if (args != null) hostBuilder.UseConfiguration((IConfiguration) new ConfigurationBuilder().AddCommandLine(args).Build()); return hostBuilder; }
这里咱们能够看到在CreateDefaultBuilder生成器中,定义了默认使用的Web服务器(UseKestrel,使用的是KestrelServer)和一些基础的配置,包括文件路径、应用配置(按appsettings.json,appsettings.{Environment}.json次序加载)、环境变量、日志,IIS集成等,若是须要的话,还能够指定其余类型的Server(IIS HTTP Server,HTTP.sys Server)和自定义Server(继承IServer)。服务器
返回到Program中,在获取到了WebHostBuilder以后紧接着就指定了启动类UseStartup<Startup>(),Build方法是WebHostBuilder最终的目的(在这个方法里面构建了管道),将构造一个WebHost返回,这里引出了咱们在ASP.NET Core - 开篇所说的重要对象:WebHost,而且运行它的Run方法用于启动应用并开始监听全部到来的HTTP请求。session
Startup方法用来指定应用程序的启动类,这里主要有两个做用:app
public class Startup { private readonly IHostingEnvironment _env; private readonly IConfiguration _config; private readonly ILoggerFactory _loggerFactory; public Startup(IHostingEnvironment env, IConfiguration config, ILoggerFactory loggerFactory) { _env = env; _config = config; _loggerFactory = loggerFactory; } // 注入服务到容器中 public void ConfigureServices(IServiceCollection services) { var logger = _loggerFactory.CreateLogger<Startup>(); if (_env.IsDevelopment()) { // Development service configuration logger.LogInformation("Development environment"); } else { // Non-development service configuration logger.LogInformation($"Environment: {_env.EnvironmentName}"); } ... } // 配置Http请求处理管道 public void Configure(IApplicationBuilder app) { ... } }
Startup 类的 执行顺序:构造 -> ConfigureServices -> Configureide
1)Startup Constructor(构造函数)函数
上面的构造函数引出了咱们开篇说的三个重要对象:IHostingEnvironment ,IConfiguration ,ILoggerFactory ,这里先讲构造函数的做用,这些对象后面会分篇讲。显而易见,这里主要是经过依赖注入实例化了该类中须要用到的对象(根据本身的业务),比较简单。ui
2) ConfigureServicesspa
首先这个方法是可选的,它的参数是IServiceCollection,这也是咱们开篇说的重要对象,并且是很是重要的对象,这是一个原生的Ioc容器,全部须要用到的服务均可以注册到里面,通常是经过约定风格services.Addxxx, 这样就可让这些服务在应用和Configure方法使用(用来构建管道)。3d
3)Configure
用于构建管道处理Http请求,管道中的每一个中间件(Middleware)组件负责请求处理和选择是否将请求传递到管道中的下一个组件,在这里咱们能够添加本身想要的中间件来处理每个Http请求,通常是使用上面的ConfigureServices方法中注册好的服务,通常的用法是 app.Usexxx,这个Usexxx方法是基于IApplicationBuilder的扩展。
须要注意的有三个地方:
public void Configure(IApplicationBuilder app) { if (env.IsDevelopment()) {// Use the Developer Exception Page to report app runtime errors. app.UseDeveloperExceptionPage(); } else {// Enable the Exception Handler Middleware to catch exceptions // thrown in the following middlewares. app.UseExceptionHandler("/Error"); } // Return static files and end the pipeline. app.UseStaticFiles(); // Use Cookie Policy Middleware to conform to EU General Data // Protection Regulation (GDPR) regulations. app.UseCookiePolicy(); // Authenticate before the user accesses secure resources. app.UseAuthentication(); // If the app uses session state, call Session Middleware after Cookie // Policy Middleware and before MVC Middleware. app.UseSession(); // Add MVC to the request pipeline. app.UseMvc(); }
若是你不想使用Startup类的话,可使用如下方式配置本身的服务注册和管道构建,虽然这种方式有点odd :)
public class Program { public static IHostingEnvironment HostingEnvironment { get; set; } public static IConfiguration Configuration { get; set; } public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { }) .ConfigureServices(services => { ... }) .Configure(app => { var loggerFactory = app.ApplicationServices .GetRequiredService<ILoggerFactory>(); var logger = loggerFactory.CreateLogger<Program>(); var env = app.ApplicationServices.GetRequiredServices<IHostingEnvironment>(); var config = app.ApplicationServices.GetRequiredServices<IConfiguration>(); logger.LogInformation("Logged in Configure"); if (env.IsDevelopment()) { ... } else { ... } var configValue = config["subsection:suboption1"]; ... }); }
这里须要注意的是,Startup只是一个概念,类的名字是能够任意的,只须要在启动项UseStartup中指定你这个启动类便可。
正如ASP.NET Core - 开篇所说的,一个ASP.NET Core应用其实就是一个控制台应用程序,它在应用启动时构建一个 Web 服务器,而且经过指定的Startup类来构建应用服务和请求管道,进而监听和处理全部的Http请求。