ASP.NET Core 中基于工厂的中间件激活详解_实用技巧

来源:脚本之家  责任编辑:小易  

ASP.NET Core开发,信磨开发并使用中间件(Middleware)。中间件是被组装成一个应用程序管道来处理请求和响62616964757a686964616fe4b893e5b19e31333363373737应的软件组件。每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组分在管道中调用之后执行特定操作。具体如图:开发中间件(Middleware)今天我们来实现一个记录ip 的中间件。1.新建一个asp.net core项目,选择空的模板。然后为项目添加一个 Microsoft.Extensions.Logging.ConsoleNuGet 命令行 ,请使用官方源。Install-Package Microsoft.Extensions.Logging.Console -Pre2.新建一个类: RequestIPMiddleware.cs复制代码 public class RequestIPMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestIPMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) { _next = next; _logger = loggerFactory.CreateLogger<RequestIPMiddleware>(); } public async Task Invoke(HttpContext context) { _logger.LogInformation("User IP: " + context.Connection.RemoteIpAddress.ToString()); await _next.Invoke(context); } }复制代悄野码3.再新建一个:RequestIPExtensions.cs复制代码 public static class RequestIPExtensions { public static IApplicationBuilder UseRequestIP(this IApplicationBuilder builder) { return builder.UseMiddleware<RequestIPMiddleware>(); } }复制滑运斗代码这样我们就编写好了一个中间件。使用中间件(Middleware)1.使用在 Startup.cs 添加 app.UseRequestIP()复制代码 public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) { loggerfactory.AddConsole(minLevel: LogLevel.Information); app.UseRequestIP();//使用中间件 app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); }复制代码然后运行程序,我选择使用Kestrel 。访问:http://localhost:5000/成功运行。这里我们还可以对这个中间件进行进一步改进,增加更多的功能,如限制访问等,中间件可以理解为一些通用的软件服务 或 软件接口, 所以是不分语言的, 最简单的比如你封装了一个SqlHelper类,简化了所有C#对数据库的访问操作等本回答被提问者采纳,不支持www.zgxue.com防采集请勿采集本网。

IMiddlewareFactory/IMiddleware是中间件激活的扩展点。

UseMiddleware扩展方法检查中间件的已注册类型是否实现IMiddleware。如果是,则使用在容器中注册的IMiddlewareFactory实例来解析IMiddleware实现,而不使用基于约定的中间件激活逻辑。中间件在应用的服务容器中注册为作用域或瞬态服务。

优点: 按客户端请求(作用域服务的注入)激活 让中间件强类型化

IMiddleware按客户端请求(连接)激活,因此作用域服务可以注入到中间件的构造函数中。

IMiddleware

IMiddleware定义应用的请求管道的中间件。InvokeAsync(HttpContext, RequestDelegate)方法处理请求,并返回代表中间件执行的Task。

使用约定激活的中间件:

public class ConventionalMiddleware{ private readonly RequestDelegate _next; public ConventionalMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, AppDbContext db) { var keyValue = context.Request.Query["key"]; if (!string.IsNullOrWhiteSpace(keyValue)) { db.Add(new Request() { DT = DateTime.UtcNow, MiddlewareActivation = "ConventionalMiddleware", Value = keyValue }); await db.SaveChangesAsync(); } await _next(context); }}

使用MiddlewareFactory激活的中间件:

public class FactoryActivatedMiddleware : IMiddleware{ private readonly AppDbContext _db; public FactoryActivatedMiddleware(AppDbContext db) { _db = db; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var keyValue = context.Request.Query["key"]; if (!string.IsNullOrWhiteSpace(keyValue)) { _db.Add(new Request() { DT = DateTime.UtcNow, MiddlewareActivation = "FactoryActivatedMiddleware", Value = keyValue }); await _db.SaveChangesAsync(); } await next(context); }}

程序会为中间件创建扩展:

public static class MiddlewareExtensions{ public static IApplicationBuilder UseConventionalMiddleware( this IApplicationBuilder builder) { return builder.UseMiddleware<ConventionalMiddleware>(); } public static IApplicationBuilder UseFactoryActivatedMiddleware( this IApplicationBuilder builder) { return builder.UseMiddleware<FactoryActivatedMiddleware>(); }}

无法通过UseMiddleware将对象传递给工厂激活的中间件:

public static IApplicationBuilder UseFactoryActivatedMiddleware( this IApplicationBuilder builder, bool option){ // Passing 'option' as an argument throws a NotSupportedException at runtime. return builder.UseMiddleware<FactoryActivatedMiddleware>(option);}

将工厂激活的中间件添加到Startup.ConfigureServices的内置容器中:

public void ConfigureServices(IServiceCollection services){ services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("InMemoryDb")); services.AddTransient<FactoryActivatedMiddleware>(); services.AddRazorPages();}

两个中间件均在Startup.Configure的请求处理管道中注册:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); } app.UseConventionalMiddleware(); app.UseFactoryActivatedMiddleware(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });}

IMiddlewareFactory

IMiddlewareFactory提供中间件的创建方法。中间件工厂实现在容器中注册为作用域服务。

可在Microsoft.AspNetCore.Http包中找到默认的IMiddlewareFactory实现(即MiddlewareFactory)。

到此这篇关于ASP.NET Core 中基于工厂的中间件激活详解的文章就介绍到这了,更多相关ASP.NET Core中间件激活内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网! 您可能感兴趣的文章:详解在ASP.NET Core 中使用Cookie中间件详解ASP.NET Core 中间件之压缩、缓存浅谈ASP.NET Core 中间件详解及项目实战Asp.Net Core 通过中间件防止图片盗链的实例

我们所说的ApplicationBuilder是对所有实现了e5a48de588b662616964757a686964616f31333363393039IApplicationBuilder接口的所有类型及其对象的统称。注册到WebHostBuilder上的启动类型具有一个用于管道定值的Configure方法,它利用作为参数的ApplicationBuilder对象进行中间件的注册。由于ApplicationBuilder与组成管道的中间件具有直接的关系,所以我们得先来说说中间件在管道中究竟体现为一个怎样的对象。中间件在请求处理流程中体现为一个类型为Func的委托对象,对于很多刚刚接触请求处理管道的读者朋友们来说,可能一开始对此有点难以理解,所以容来略作解释。我们上面已经提到过RequestDelegate这么一个委托,它相当于一个Func对象,该委托对象表示针对提供的HttpContext所做进行一项处理操作,这项操作代表某个中间件针对请求的处理。那为何我们不直接用一个RequestDelegate对象来表示一个中间件,而将它表示成一个Func对象呢?在大部分应用中,我们会针对具体的请求处理需求注册多个不同的中间件,这些中间件按照注册时间的先后顺序进行排列进而构成我们所谓的请求处理管道。对于某个中间件来说,在它完成了自身的请求处理任务之后,需要将请求传递给下一个中间件作后续的处理。Func中作为输入参数的RequestDelegate对象代表一个委托链,体现了后续中间件对请求的处理,当前中间件将自身实现的请求处理任务添加到这个委托链中,而返回RequestDelegate对象代表最新的委托链。以右图所示的管道为例,如果用一个Func来表示中间件B,那么作为输入参数的RequestDelegate对象代表的是C对请求的处理操作,而返回值则代表B和C先后对请求处的处理操作。如果一个Func代表第一个从服务器接收请求的中间件(比如A),那么执行该委托对象返回的RequestDelegate实际上体现了整个管道对请求的处理。在对中间件有了充分的了解之后,我们来看看用于注册中间件的IApplicationBuilder接口的定义。如下所示的是经过裁剪后的IApplicationBuilder接口的定义,我们只保留了两个核心的方法,其中Use方法实现了针对中间件的注册,另一个Build方法则将所有注册的中间件转换成一个RequestDelegate对象。1:publicinterfaceIApplicationBuilder2:{3:RequestDelegateBuild();4:IApplicationBuilderUse(Funcmiddleware);5:}从编程便利性考虑,很多预定义的中间件都具有用于注册的扩展方法,比如我们调用扩展方法UseStaticFiles来注册处理静态文件请求的中间件。对于我们演示的发布图片的应用来说,它也是通过调用一个具有如下定义的扩展方法UseImages来注册处理图片请求的中间件。1:publicstaticclassApplicationBuilderExtensions2:{3:publicstaticIApplicationBuilderUseImages(thisIApplicationBuilderapp,stringdirectory)4:{5:Funcmiddleware=next=>6:{7:returncontext=>8:{9:stringfileName=context.Request.Url.LocalPath.TrimStart('/');10:if(string.IsNullOrEmpty(Path.GetExtension(fileName)))11:{12:fileName+=".jpg";13:}14:fileName=Path.Combine(directory,fileName);15:context.Response.WriteFile(fileName,"image/jpg");16:returnnext(context);17:};18:};19:returnapp.Use(middleware);20:}21:}ASP.NETCore默认使用的是一个类型为ApplicationBuilder的对象来注册中间件,我们采用如下的代码片断来模拟它的实现逻辑。我们采用一个List>对象来存放所有注册的中间件,并调用Aggregate方法将它转换成一个RequestDelegate对象。1:publicclassApplicationBuilder:IApplicationBuilder2:{3:privateIList>middlewares=newList>();4:5:publicRequestDelegateBuild()6:{7:RequestDelegateseed=context=>Task.Run(()=>{});8:returnmiddlewares.Reverse().Aggregate(seed,(next,current)=>current(next));9:}10:11:publicIApplicationBuilderUse(Funcmiddleware)12:{13:middlewares.Add(middleware);14:returnthis;15:}16:}ASP.NETCore并不会直接创建ApplicationBuilder对象来注册中间件,而是利用对应的工厂来创建它。创建爱你ApplicationBuilder的工厂通过接口IApplicationBuilderFactory表示,在模拟的管道中我们将这个接口简化成如下的形式,该接口的默认实现者ApplicationBuilderFactory会直接创建一个ApplicationBuilder类型的对象。1:publicinterfaceIApplicationBuilderFactory2:{3:IApplicationBuilderCreateBuilder();4:}5:6:publicclassApplicationBuilderFactory:IApplicationBuilderFactory7:{8:publicIApplicationBuilderCreateBuilder()9:{10:returnnewApplicationBuilder();11:}12:}内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • 手把手教你aspnetcore webapi数据验证的实现
  • .net core webapi jwt 更为清爽的认证详解
  • asp.net内置对象之server对象(概述及应用)
  • asp.net 通过useragent判断智能设备(android,ios)
  • asp.net数组删除重复值实现代码
  • 浅谈.net反射机制的性能优化 附实例下载
  • .net事件监听机制的局限与扩展分析
  • asp.net―001:gridview绑定list、页面返回值具体实现
  • asp.net如何将dataset转换成josn并输出
  • 进度条在.net导入excel时的应用实例
  • 终于知道什么情况下需要实现.NET Core中的IOptions...
  • net core支持中间件开发吗
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础应用实用技巧自学过程首页asp.net详解在asp.net core 中使用cookie中间件详解asp.net core 中间件之压缩、缓存浅谈asp.net core 中间件详解及项目实战asp.net core 通过中间件防止图片盗链的实例手把手教你aspnetcore webapi数据验证的实现.net core webapi jwt 更为清爽的认证详解asp.net内置对象之server对象(概述及应用)asp.net 通过useragent判断智能设备(android,ios)asp.net数组删除重复值实现代码浅谈.net反射机制的性能优化 附实例下载.net事件监听机制的局限与扩展分析asp.net―001:gridview绑定list、页面返回值具体实现asp.net如何将dataset转换成josn并输出进度条在.net导入excel时的应用实例未将对象引用设置到对象的实例 (java正则表达式 pattern和matcheasp.net(c#)网页跳转七种方法小结未能加载文件或程序集“xxx”或它asp.net“服务器应用程序不可用”asp.net中的几种弹出框提示基本实asp.net gridview 72般绝技asp.net生成excel并导出下载五种asp.net对路径"xxxxx"asp.net汉字转拼音和获取汉字首字asp.net 2.0 中收集的小功能点(转).net core webapi通过中间件获取请求和响从别人那拷下来的几点session使用的经验asp.net下cookies的丢失和中文乱码asp.net单文件带进度条上传的解决方案asp.net mvc分页和排序功能实现asp.net 页生命周期概述(小结)利用service fabric承载eshop on contain根据eval()函数绑定的值,来显示gridview中asp.net根据日期算出天数的小例子
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved