startup
配置入口:
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
Startup仅仅是个约定的名字,完全可以换成其他名字
两个重要的方法:
public void ConfigureServices(IServiceCollection services)
可选的方法。IServiceCollection通过DI注入实例
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
必须方法。IApplicationBuilder、IHostingEnvironment等都是通过DI注入实例
startup类的主要作用是提供用一个便捷的配置入口,主要提供ConfigureServices
和ConfigureServices
两个方法。其本质是如下代码所示:
WebHost.CreateDefaultBuilder ()
.ConfigureServices (services =>
services.AddSingleton<IComponent, ComponentInstance> ()
)
.Configure (app => {
var component = app.ApplicationServices.GetRequiredService<IComponent> ();
app.Run (async (context) =>
await context.Response.WriteAsync ($"Name is {component.Name}")
);
})
.Build ();
由此可见,startup只是提供了
ConfigureServices
和Configure
两个重要的方法而已。除了这两个方法外,也可放置其他可用的方法,如Configure[Environment]
、ConfigureServices[Environment]
。ConfigureServices
先于Configure
执行。因为Configure的回调函数只接受一个IApplicationBuilder,因此需要手动调用app.ApplicationServices.GetRequiredService<IComponent> ()
,以获取依赖注入的实例。
请求管道(pipeline)
主要包括`run`,`use`,`Map`,`MapWhen`几种方法。Use
拦截管道,注入自己的逻辑后可直接返回,也可调用next()方法继续执行下个管道方法。use和run都接受一个RequestDelegate作为唯一参数,RequestDelegate的参数是HttpContext。
public void Configure (IApplicationBuilder app) { app.Use (async (context, next) => { if (context.Request.Path == "/foo") { await context.Response.WriteAsync ($"Welcome to Foo"); } else { await next (); } }); app.Use (async (context, next) => { if (context.Request.Path == "/bar") { await context.Response.WriteAsync ($"Welcome to Bar"); } else { await next (); } }); app.Run (async (context) => await context.Response.WriteAsync ($"Welcome to the default") ); }
Run
最后执行。直接打断整个请求,立即返回,因此一般放置于最后。
app.Run (async (context) => await context.Response.WriteAsync ($"Name is {component.Name}") );
Map, MapWhen
app.Map ("/foo", config => config.Use (async (context, next) => await context.Response.WriteAsync ("Welcome to /foo") ) ); app.MapWhen ( context => context.Request.Method == "POST" && context.Request.Path == "/bar", config => config.Use (async (context, next) => await context.Response.WriteAsync ("Welcome to POST /bar") ) );
自定义中间件
定义中间件类:
public class RequestLogMiddleware { private RequestDelegate _next; public RequestLogMiddleware (RequestDelegate requestDelegate) { _next = requestDelegate; } public async Task Invoke(HttpContext context) { Console.WriteLine($"request path: {context.Request.Path}\r\n"); await context.Response.WriteAsync($"request path: {context.Request.Path}\r\n"); await _next.Invoke(context); Console.WriteLine("finish request!"); await context.Response.WriteAsync("finish request!\r\n"); } }
添加IApplicationBuilder扩展方法
public static IApplicationBuilder UseRequestLogger(this IApplicationBuilder builder) { return builder.UseMiddleware<RequestLogMiddleware>(); }
Configure()方法中使用中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRequestLogger(); // 自定义中间件 app.Use(async (context, next) => { await context.Response.WriteAsync("in use1 middleware!\r\n"); await next(); await context.Response.WriteAsync("out use1 middleware!\r\n"); }); app.Use(async (context, next) => { await context.Response.WriteAsync("in use2 middleware!\r\n"); await next(); await context.Response.WriteAsync("out use2 middleware!\r\n"); }); app.Run(async (context) => { await context.Response.WriteAsync("in run middleware!\r\n"); }); }
执行结果:
request path: /api/values in use1 middleware! in use2 middleware! in run middleware! out use2 middleware! out use1 middleware! finish request!