当我们来到一个陌生的环境,第一件事就是找到厕所在哪。
当我们接触一份新框架时,第一件事就是找到程序入口,即Main方法
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
代码很简单,典型的建造者模式:通过IHostBuilder创建一个通用主机(Generic Host),然后启动它(至于什么是通用主机,咱们后续的文章会说到)。咱们不要一上来就去研究CreateDefaultBuilder、ConfigureWebHostDefaults这些方法的源代码,应该去寻找能看的见、摸得着的,很明显,只有Startup。
Startup类Startup类承担应用的启动任务,所以按照约定,起名为Startup,不过你可以修改为任意类名(强烈建议类名为Startup)。
默认的Startup结构很简单,包含:
构造函数
Configuration属性
ConfigureServices方法
Configure方法
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. // 该方法由运行时调用,使用该方法向DI容器添加服务 public void ConfigureServices(IServiceCollection services) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // 该方法由运行时调用,使用该方法配置HTTP请求管道 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { } }
Startup构造函数当使用通用主机(Generic Host)时,Startup构造函数支持注入以下三种服务类型:
IConfiguration
IWebHostEnvironment
IHostEnvironment
public Startup( IConfiguration configuration, IHostEnvironment hostEnvironment, IWebHostEnvironment webHostEnvironment) { Configuration = configuration; HostEnvironment = hostEnvironment; WebHostEnvironment = webHostEnvironment; } public IConfiguration Configuration { get; } public IHostEnvironment HostEnvironment { get; set; } public IWebHostEnvironment WebHostEnvironment { get; set; }
这里你会发现 HostEnvironment 和 WebHostEnvironment 的实例是同一个。别着急,后续文章我们聊到Host的时候,你就明白了。
ConfigureServices该方法是可选的
该方法用于添加服务到DI容器中
该方法在Configure方法之前被调用
该方法要么无参数,要么只能有一个参数且类型必须为IServiceCollection
该方法内的代码大多是形如Add{Service}的扩展方法
常用的服务有(部分服务框架已默认注册):
AddControllers:注册Controller相关服务,内部调用了AddMvcCore、AddApiExplorer、AddAuthorization、AddCors、AddDataAnnotations、AddFormatterMappings等多个扩展方法
AddOptions:注册Options相关服务,如IOptions<>、IOptionsSnapshot<>、IOptionsMonitor<>、IOptionsFactory<>、IOptionsMonitorCache<>等。很多服务都需要Options,所以很多服务注册的扩展方法会在内部调用AddOptions
AddRouting:注册路由相关服务,如IInlineConstraintResolver、LinkGenerator、IConfigureOptions<RouteOptions>、RoutePatternTransformer等
AddAddLogging:注册Logging相关服务,如ILoggerFactory、ILogger<>、IConfigureOptions<LoggerFilterOptions>>等
AddAuthentication:注册身份认证相关服务,以方便后续注册JwtBearer、Cookie等服务
AddAuthorization:注册用户授权相关服务
AddMvc:注册Mvc相关服务,比如Controllers、Views、RazorPages等
AddHealthChecks:注册健康检查相关服务,如HealthCheckService、IHostedService等
Configure该方法是必须的
该方法用于配置HTTP请求管道,通过向管道添加中间件,应用不同的响应方式。
该方法在ConfigureServices方法之后被调用
该方法中的参数可以接受任何已注入到DI容器中的服务
该方法内的代码大多是形如Use{Middleware}的扩展方法
该方法内中间件的注册顺序与代码的书写顺序是一致的,先注册的先执行,后注册的后执行
常用的中间件有
UseDeveloperExceptionPage:当发生异常时,展示开发人员异常信息页。如图
UseRouting:路由中间件,根据Url中的路径导航到对应的Endpoint。必须与UseEndpoints搭配使用。
UseEndpoints:执行路由所选择的Endpoint对应的委托。
UseAuthentication:身份认证中间件,用于对请求用户的身份进行认证。比如,早晨上班打卡时,管理员认出你是公司员工,那么才允许你进入公司。