网站备案通管局,山东和城乡建设厅网站,c网站建设,新手怎么建立网站1.前言中间件#xff08;middleware#xff09;是一种装配到应用管道以处理请求和响应的组件。每个组件#xff1a;●可选择是否将请求传递到管道中的下一个组件。●可在管道中的下一个组件前后执行工作。请求委托#xff08;request delegates#xff09;用于建立请求管道… 1.前言中间件middleware是一种装配到应用管道以处理请求和响应的组件。每个组件●可选择是否将请求传递到管道中的下一个组件。●可在管道中的下一个组件前后执行工作。请求委托request delegates用于建立请求管道request pipeline请求委托处理每个HTTP请求。请求委托通过使用IApplicationBuilder类型的Run、Map和Use扩展方法来配置并在Strartup类中传给Configure方法。每个单独的请求委托都可以被指定为一个内嵌匿名方法称为并行中间件in-line middleware或者其定义在一个可重用的类中。这些可重用的类被称作“中间件”或“中间件组件”。请求管道中的每个中间件组件负责调用管道中的下一个组件或使管道短路。当中间件短路时它被称为“终端中间件”terminal middleware因为它阻止中间件进一步处理请求。2.使用 IApplicationBuilder 创建中间件管道ASP.NET Core请求管道包含一系列请求委托依次调用。下图演示了这一概念。沿黑色箭头执行。每个委托中间件均可在下一个委托前后执行操作。任何委托都能选择停止传递到下一个委托转而自己处理该请求这就是请求管道的短路下面会举例说明。而且是一种有意义的设计因为它可以避免不必要的工作。比如一个授权authorization中间件只有通过身份验证之后才能调用下一个委托否则它就会被短路并返回“Not Authorized”的响应。所以应尽早在管道中调用异常处理委托这样它们就能捕获在管道的后期阶段发生的异常。现在我们来演示下用一个简单的ASP.NET Core应用程序建立单个请求委托处理每个HTTP请求这种情况不包括实际请求管道public class Startup{public void Configure(IApplicationBuilder app) { app.Run(async context {await context.Response.WriteAsync(Hello, World!); }); }}响应结果由上面我们可以看到运行时输出的是Run委托消息然后我们再定义多一个请求委托看看效果请看如下代码public void Configure(IApplicationBuilder app){//第一个委托Run app.Run(async context {await context.Response.WriteAsync(Hello, World!); });//第二个委托Run app.Run(async context {await context.Response.WriteAsync(Hey, World!); });}响应结果由上述代码可以看到我们定义两个Run委托但是运行第一个Run委托的时候就已经终止了管道这是为什么呢因为Run方法又称为短路管道它不会调用next请求委托。因此Run方法一般在管道尾部被调用。Run是一种约定有些中间件组件可能会暴露他们自己的Run方法而这些方法只能在管道末尾处运行。让我们再来看看如下代码public void Configure(IApplicationBuilder app){ app.Use(async (context, next) { context.Response.ContentType text/plain; charsetutf-8;await context.Response.WriteAsync(进入第一个委托 执行下一个委托之前\r\n);//调用管道中的下一个委托await next.Invoke();await context.Response.WriteAsync(结束第一个委托 执行下一个委托之后\r\n); }); app.Run(async context {await context.Response.WriteAsync(进入第二个委托\r\n);await context.Response.WriteAsync(Hello from 2nd delegate.\r\n);await context.Response.WriteAsync(结束第二个委托\r\n); });}响应结果通过响应结果我们可以看到Use方法将多个请求委托链接在一起。而next参数表示管道中的下一个委托。可通过不调用next 参数使管道短路通常可在下一个委托前后执行操作。3.顺序向Startup.Configure方法添加中间件组件的顺序定义了在请求上调用它们的顺序以及响应的相反顺序。此排序对于安全性、性能和功能至关重要。以下Startup.Configure方法将为常见应用方案添加中间件组件●异常/错误处理Exception/error handling●HTTP严格传输安全协议HTTP Strict Transport Security Protocol●HTTPS重定向HTTPS redirection●静态文件服务器Static file server●Cookie策略实施Cookie policy enforcement●身份验证Authentication●会话Session●MVC请看如下代码从上述示例代码中每个中间件扩展方法都通过Microsoft.AspNetCore.Builder命名空间在 IApplicationBuilder上公开。但是为什么我们要按照这个顺序去添加中间件组件呢下面我们挑几个中间件来了解下。●UseExceptionHandler异常/错误处理是添加到管道的第一个中间件组件。因此我们可以捕获在应用程序调用中发生的任何异常。那为什么要将异常/错误处理放在第一位呢那是因为这样我们就不用担心因前面中间件短路而导致捕获不到整个应用程序所有异常信息。●UseStaticFiles静态文件中间件在管道中提前调用方便它可以处理请求和短路而无需通过剩余中间组件。也就是说静态文件中间件不用经过UseAuthentication身份验证检查就可以直接访问即可公开访问由静态文件中间件服务的任何文件包括wwwroot下的文件。●UseAuthentication身份验证仅在MVC选择特定的Razor页面或Controller和Action之后才会发生。经过上面描述大家都了解中间件顺序的重要性了吧。以下示例演示中间件的排序其中静态文件的请求在响应压缩中间件之前由静态文件中间件进行处理。静态文件不会按照中间件的顺序进行压缩。可以压缩来自 UseMvcWithDefaultRoute的 MVC 响应。示例public void Configure(IApplicationBuilder app){// Static files not compressed by Static File Middleware. app.UseStaticFiles(); app.UseResponseCompression(); app.UseMvcWithDefaultRoute();}4.Use、Run和Map方法你可以使用Use、Run和Map配置HTTP管道。●UseUse方法可使管道短路即不调用 next 请求委托。第二节点有示例代码演示。●RunRun是一种约定并且某些中间件组件可公开在管道末尾运行的Run[Middleware]方法。第二节点有示例代码演示。●MapMap扩展用作创建管道分支。Map*给请求路径的匹配项来创建请求管道分支。如果请求路径以给自定义路径开头则执行分支。下面我们来看看这段代码public class Startup{private static void HandleMapTest1(IApplicationBuilder app) { app.Run(async context {await context.Response.WriteAsync(Map Test 1); }); }private static void HandleMapTest2(IApplicationBuilder app) { app.Run(async context {await context.Response.WriteAsync(Map Test 2); }); }public void Configure(IApplicationBuilder app) { app.Map(/map1, HandleMapTest1); app.Map(/map2, HandleMapTest2); app.Run(async context {await context.Response.WriteAsync(Hello from non-Map delegate. p); }); }}下面表格使用前面的代码显示来自http://localhost:5001的请求和响应。请求响应localhost:5001Hello from non-Map delegate.localhost:5001/map1Map Test 1localhost:5001/map2Map Test 2localhost:5001/map3Hello from non-Map delegate.由上面可以了解到当使用Map方法时将从HttpRequest.Path中删除匹配的路径段并针对每个请求将该路径追加到HttpRequest.PathBase。MapWhen基于给定谓词的结果创建请求管道分支。FuncHttpContext, bool类型的任何谓词均可用于将请求映射到管道的新分支HandleBranch。在以下示例中谓词用于检测查询字符串变量branch是否存在public class Startup{private static void HandleBranch(IApplicationBuilder app) { app.Run(async context {var branchVer context.Request.Query[branch];await context.Response.WriteAsync($Branch used {branchVer}); }); }public void Configure(IApplicationBuilder app) { app.MapWhen(context context.Request.Query.ContainsKey(branch), HandleBranch); app.Run(async context {await context.Response.WriteAsync(Hello from non-Map delegate. p); }); }}下面表格使用前面的代码显示来自http://localhost:5001的请求和响应。请求响应http://localhost:5001Hello from non-Map delegate. phttps://localhost:5001/?branchmasterBranch used masterMap支持嵌套例如public void Configure(IApplicationBuilder app){ app.Map(/level1, level1App { level1App.Map(/level2a, level2AApp {// /level1/level2a processing }); level1App.Map(/level2b, level2BApp {// /level1/level2b processing }); });}此外Map 还可同时匹配多个段public class Startup{private static void HandleMultiSeg(IApplicationBuilder app) { app.Run(async context {await context.Response.WriteAsync(Map multiple segments.); }); }public void Configure(IApplicationBuilder app) { app.Map(/map1/seg1, HandleMultiSeg); app.Run(async context {await context.Response.WriteAsync(Hello from non-Map delegate.); }); }}5.编写中间件重点虽然ASP.NET Core为我们提供了一组丰富的内置中间件组件但在某些情况下你可能需要写入自定义中间件。5.1中间件类通常中间件应该封装在自定义类中并且通过扩展方法公开。下面我们自定义一个查询当前区域性的中间件public class Startup{public void Configure(IApplicationBuilder app) { app.Use((context, next) {var cultureQuery context.Request.Query[culture];if (!string.IsNullOrWhiteSpace(cultureQuery)) {var culture new CultureInfo(cultureQuery); CultureInfo.CurrentCulture culture; CultureInfo.CurrentUICulture culture; }// Call the next delegate/middleware in the pipelinereturn next(); }); app.Run(async (context) {await context.Response.WriteAsync( $Hello {CultureInfo.CurrentCulture.DisplayName}); }); }}可通过传入区域性参数测试该中间件。例如 http://localhost:7997/?culturezh、http://localhost:7997/?cultureen。但是为了更好管理代码我们应该把委托函数移到自定义类去//自定义RequestCultureMiddleware类public class RequestCultureMiddleware{private readonly RequestDelegate _next;public RequestCultureMiddleware(RequestDelegate next) { _next next; }public async Task InvokeAsync(HttpContext context) { context.Response.ContentType text/plain; charsetutf-8;var cultureQuery context.Request.Query[culture];if (!string.IsNullOrWhiteSpace(cultureQuery)) {var culture new CultureInfo(cultureQuery); CultureInfo.CurrentCulture culture; CultureInfo.CurrentUICulture culture; }// Call the next delegate/middleware in the pipelineawait _next(context); }}5.2中间件扩展方法中间件扩展方法可以通过IApplicationBuilder公开中间件。示例创建一个RequestCultureMiddlewareExtensions扩展类并通过IApplicationBuilder公开public static class RequestCultureMiddlewareExtensions{public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder) {return builder.UseMiddlewareRequestCultureMiddleware(); }}再通过Startup.Configure方法调用中间件public class Startup{public void Configure(IApplicationBuilder app) { app.UseRequestCulture(); app.Run(async (context) {await context.Response.WriteAsync( $Hello {CultureInfo.CurrentCulture.DisplayName}); }); }}响应结果由此整个自定义ASP.NET Core中间件完成。6.按请求依赖项因为中间件是在应用程序启动时构建的而不是每个请求时构建所以在每个请求期间中间件构造函数使用的范围内生命周期服务不与其他依赖关系注入类型共享。如果您必须在中间件和其他类型之间共享作用域服务请将这些服务添加到Invoke方法的签名中。Invoke方法可以接受由依赖注入DI填充的其他参数。示例public class CustomMiddleware{private readonly RequestDelegate _next;public CustomMiddleware(RequestDelegate next) { _next next; }// IMyScopedService is injected into Invokepublic async Task Invoke(HttpContext httpContext, IMyScopedService svc) { svc.MyProperty(1000);await _next(httpContext); }}public static class CustomMiddlewareExtensions{public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder builder) {return builder.UseMiddlewareCustomMiddleware(); }}public interface IMyScopedService{void MyProperty(decimal input);}public class MyScopedService : IMyScopedService{public void MyProperty(decimal input) { Console.WriteLine(MyProperty is input); }}public void ConfigureServices(IServiceCollection services){//注入DI服务 services.AddScopedIMyScopedService, MyScopedService();}响应结果参考文献ASP.NET Core中间件写入自定义ASP.NET Core中间件原文地址https://www.cnblogs.com/wzk153/p/10904988.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com