Startup 类
Startup类用于配置服务和应用的请求管道。
1.使用ConfigureServices方法选择性的配置应用的服务,如Mvc。服务是一个提供应用功能的可重用组件。在ConfigureServices方法中注册服务,并通过依赖注入或ApplicationServices在整个应用中使用服务。
2.使用Configure方法来创建应用的请求处理管道,注册中间件。
在构建应用主机时指定 Startup 类。 通常,通过在Program.cs中调用 UseStartup<TStartup> 方法来指定 Startup 类。在应用启动时,ASP.NET Core 运行时会调用 ConfigureServices 和 Configure,必须定义Configure,ConfigureServices 可以选择的定义。
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
ConfigureServices 方法
ConfigureServices是可以配置的、配置选项按约定设置,在Configure方法之前执行,并由主机调用以配置应用程序的服务。在调用Startup之前主机webhost会自己配置某些服务,例如Logging、依赖关系注入 (DI) 服务等。
对于需要大量设置的功能,IServiceCollection 上有 Add{Service}
扩展方法。 例如,AddDbContext、AddDefaultIdentity、AddEntityFrameworkStores 和 AddRazorPages
将服务添加到服务容器,使其在应用和 Configure
方法中可用。 服务通过依赖关系注入或 ApplicationServices 进行解析。
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
Configure 方法
Configure用于构建请求管道的中间件,来处理http请求,例如处理异常、静态文件等。
每个 Use
扩展方法将一个或多个中间件组件添加到请求管道,例如UseStaticFiles 配置中间件提供静态文件。请求管道中的每个中间件组件负责调用管道中的下一个组件,或在适当情况下使链发生短路。可以在 Configure
方法签名中指定其他服务,如 IWebHostEnvironment
、ILoggerFactory
或 ConfigureServices
中定义的任何内容。 如果这些服务可用,则会被注入。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
不使用Startup配置Configure和ConfigureServices
不使用Startup的话需要在Host上调用ConfigureServices和Configure方法,多次调用ConfigureSerivces将会追加到下一个方法,但是多次调用Configure只会使用最后一个调用的Configure方法。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }) .Configure(app => { app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); });
使用StartupFilter扩展Startup
我们知道Startup.cs中的Configure方法内可以注册中间件,也可以利用另一个叫做StartupFilter的对象来实现。所谓的StartupFilter是对所有实现了IStartupFilter接口的类型及其对象的统称。IStartupFilter接口定义了如下一个唯一的方法Configure,该方法的参数next返回的Action<IApplicationBuilder>对象体现了后续StartupFilter和Startup对中间件的注册,而自身对中间件的注册则实现在返回的Action<IApplicationBuilder>对象中。
我们可以采用服务注册的方式注册多个StartupFilter,多个的话按自上而下的注册顺序执行。具体来说,StartupFilter具有如下两种不同的注册方式,一种是通过调用WebHost的ConfigureServices方法以服务的形式注册所需的StartupFilter,另一种则是将针对StartupFilter的服务注册实现在启动类的ConfigureServices方法上。
通过Startup和StartupFilter进行注册,唯一的区别在于StartupFilter注册的中间件会先执行。
我们先创建一个中间件:
public class MiddlewareBase { private readonly RequestDelegate _next; public MiddlewareBase(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { await httpContext.Response.WriteAsync($"Startupfilter=>"); await _next(httpContext); } }
然后我们再建一个类继承IStartupFilter,实现它的方法Configure,我们将中间件的注册实现在返回的Action<IApplicationBuilder>对象中。
public class MiddlewareBaseStartupFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return builder => { builder.UseMiddleware<MiddlewareBase>(); next(builder); }; } }
之后在Startup.cs的ConfigureServices中注册MiddlewareBaseStartupFilter。
services.AddSingleton<IStartupFilter, MiddlewareBaseStartupFilter>();
最后在Startup.cs的Configure中注册两个中间件,运行查看输出结果。
app.Use(async (context, next) => { await context.Response.WriteAsync("Hello from 1nd delegate."); await next.Invoke(); }); app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); });