这两个是Core新增的文件,非常重要
Program.cs
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>(); }); }
咱们把Main方法里的代码拆成3步,这3步其实就是创建一个web服务器并启动,最重要的其实就是第一步了。
var hostBuilder = CreateHostBuilder(args); var host = hostBuilder.Build(); host.Run();
CreateHostBuilder方法中的Host.CreateDefaultBuilder(args),创建一个默认的builder,并完成各种基本配置;ConfigureWebHostDefaults方法,指定一个web服务器(kestrel)。
Startup.cs
是kestrel服务器和mvc的关联节点
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. public void ConfigureServices(IServiceCollection services) { services.AddSession();//该怎么用session services.AddControllersWithViews(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseSession();//表示请求需要使用session 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.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } }
Configure 方法是配置http请求处理的过程。
可以在方法最上面这样写
app.Use(a => { return async c => { await c.Response.WriteAsync("统一返回"); }; });
这样不管访问网站的哪个页面,都会返回这句话,跟你访问的控制器无关,这里只跟请求有关。
可以看到有各种app.useXXXXX,就是在为管道添加各种中间件,我们也可以这么写
app.Use(next => { return async c => { if (c.Request.Query.ContainsKey("name")) { await next.Invoke(c); } else { await c.Response.WriteAsync("缺少name"); } }; });
这个很简单,如果请求有key为name的参数,继续执行其他中间件,否则,提示缺少name。
中间件的执行顺序不像之前framework那种管道,固定了事件的顺序(同时在事件的前后预注册了各自的before/after事件,让开发者能自定义一些功能),core开发者可以随意一层一层套,也可以改变中间件的执行顺序。
我们也可以自己定义中间件,在Configure 方法中引用,首先创建一个DontTakeMyImg类,通过依赖注入RequestDelegate委托,然后实现Invoke方法,方法体很简单,如果直接访问的是.jpg格式,提示不能直接访问。
public class DontTakeMyImg { private readonly RequestDelegate _next; public DontTakeMyImg(RequestDelegate next) { this._next = next; } public async Task Invoke(HttpContext context) { string url = context.Request.Path.Value; if (url.Contains(".jpg")) { await context.Response.WriteAsync("不许直接访问图片"); } else { await _next(context); } } }
在startup.cs中注册中间件,这里Middleware是命名空间
app.UseMiddleware<Middleware.DontTakeMyImg>();
这样就有效果了