浅谈ASP.NET Core 2.0 中间件(译)

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

“你只是朕的一个妃子,不要太看大自己”坐在皇位上的他看着身穿白衣满身伤痕的她“只是妃子…”她眼神迷离恍惚,眼赤红,早已哭不出眼泪“来人,将贤妃拖下去,打入天牢,严刑拷打,让她说出皇后到底是怎么被她残害的!”他心中有数,她变了,原来深爱着的白霖雪早已变了,变得心狠手辣,甚至毒死了皇后,他只好这样,为皇后报仇,也是对她的惩戒“高彦…这个仇,我记住了,说什么相信我,不都是谎言,三年后,我必夺你皇位,拿回属于我们白家的东西!”她嘶哑着声音,被侍卫拖着出去,身下还流着血,她的孩子……她的孩子……牢中“小姐,已经准备好了…出发吧…”追风看着面前的的女子,她的黑发竟变成白发,身上大大小小的伤痕布满了全身,就

问题

如何创建一个最简单的ASP.NET Core中间件?

俗语说“书中自有黄金屋,书中自有颜如玉”,书当然是我们有益的精神食粮。不过最近就有报道,说书中竟然有甲醛。原来,江苏泰州陶女士一家三口,从去年底开始,陆续出现咳、鼻炎等症状,疑似是甲醛中毒,一查,居然和家里的书多有关。对此,我们的记者就专门做了新书和旧书的甲醛含量检测,结果究竟如何?住在江苏泰州的陶女士夫妇,是大家公认的学霸,夫妻俩既不逛街也不打游戏,最中意的就是窝在家里看书。陶女士的丈夫“网上有促销活动,基本上就买书了。一个月买三四次吧。”很快,陶女士家里的客厅、睡房都被书本杂志堆得很满。陶女士说,家里的藏书少说也有几万本了。书是越来越多,一家三口的身体状况却是每况愈下。陶女士“不仅我咳,我

答案

使用VS创建一个ASP.NET Core 2.0的空项目,注意Startup.cs中的Configure()方法:

感谢邀请。首先说一下,戒指戴手上,不同位置是什么意思。比如,五个手指头,分别代表应该是“追、求、订、婚、离”五个字说明将戒指分别戴在5个手指上的含义和暗示。具体到每个人,那么戴一个两个的很正常。戴多个以上的,那意思就多了。1极度炫富女。2物品控。具体到人,也就是戒指控。3心里有疾病者。也就是我们通常说的精神方面。4,控制欲,占有欲极强者。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.Run(async (context) =>
  {
    await context.Response.WriteAsync("Hello World! (Run)");
  });
}

宝宝爱黏人——安全感需求来了美国加州大学医学院精神学临床教授阿兰·斯格尔解释说:“1~2岁,是孩子出现黏人行为的最明显阶段,他们把妈妈或看护人看作一个‘安全基地’,当有安全需求时,就会返回看护人身边。”宝宝出生后,缺乏最基本的生活自理能力,长期处在妈妈的照料下,必然会形成对妈妈的依赖。所以说,宝宝黏人是一种正常的心理发展,是对熟悉的亲人逐渐产生依恋情绪的表现,也是宝宝成长过程中不可避免的现象。宝宝妈妈之间温暖、亲密的关系,适度的依恋(即黏人现象),可使宝宝既得到满足,又心情愉快。宝宝有了这种安全依恋感时,不但能在陌生的环境中克服焦虑和恐惧,还能去探索周围的新鲜事物,并且发展社交能力和认知能力。

比较好的创建请求管道的方法是使用IApplicationBuilder上的扩展方法:

public static void RunHelloWorld(this IApplicationBuilder app) { app.Run(async (context) => { await context.Response.WriteAsync("Hello World! (Run)"); }); }

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.RunHelloWorld(); }

运行,此时页面显示:

上面我们使用IApplicationBuilder.Run()来配置中间件,另外一种方法是IApplicationBuilder.Use():

public static void UseHelloWorld(this IApplicationBuilder app) { app.Use(async (context, next) => { await context.Response.WriteAsync("Hello World! (Use)\n"); await next(); }); }

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); app.RunHelloWorld(); }

运行,此时页面显示:

将中间件作为单独的类定义是更好的实践方法:

public class HelloWorldMiddleware { private readonly RequestDelegate _next; public HelloWorldMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync("Hello World! (Use in Class)\n"); await _next(context); } } public static class UseHelloWorldInClassExtensions { public static IApplicationBuilder UseHelloWorldInClass(this IApplicationBuilder app) { return app.UseMiddleware<HelloWorldMiddleware>(); } }

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); app.UseHelloWorldInClass(); app.RunHelloWorld(); }

运行,此时页面显示:

讨论

中间件是一个拦截HTTP请求和响应消息的组件。我们通过创建这些组件链,来为我们的应用程序创建一个请求管道。

我们通过Configure()方法的IApplicationBuilder参数来创建这个请求管道,IApplicationBuilder参数有如下方法:

    Run():添加中间件并终止请求管道(也就是说不再调用下一个中间件)。 Use():添加中间件,使用lambda表达式或者一个具体的类。 Map():根据请求路径添加中间件。

Run

这个方法接受RequestDelegate委托作为参数,当委托方法被调用时接受HttpContext参数。这个委托方法返回void,因为它会终止请求管道。

Use

这个方法接受Func委托作为参数,此委托方法有两个参数,分别是HttpContext和指向下一个中间件的next,返回空(Task)。如果没有调用下一个中间件,就会终止请求管道(和Run效果一样)。

UserMiddleware

当通过单独类创建中间件时,我们使用UseMiddleware方法,并将具体的实现类型作为泛型参数。

在中间件类中,有两个部分很重要:

1. 构造函数接受RequestDelegate。当调用此委托时会将当前请求传入下一个中间件。

2. 它拥有一个Invoke方法,接收HttpContext参数并返回空(Task)。当需要用到中间件时,框架会主动调用这个方法。

注:在单独类中实现中间件,并用UseMiddleware封装起来是最佳实践。

扩展方法

需要注意扩展方法的不同之处,RunXXX不会返回值,而UseXXX会返回值(IApplicationBuilder)。这是因为Run()终止请求管道,而Use()可能会链接到其他的中间件。

顺序

中间件按照它们在Configure()方法出现的顺序依次被调用。而返回到客户端的响应也会经历相同的中间件管道。

源代码下载

原文:https://tahirnaushad.com/2017/08/14/asp-net-core-middleware/

扩展阅读,根据您访问的内容系统为您准备了以下内容,希望对您有帮助。

net core支持中间件开发吗

ASP.NET Core开发,开发并使用中间件(Middleware)。

中间件是被组装成一个应用程序管道来处理请求和响应的软件组件。

每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组分在管道中调用之后执行特定操作。

具体如图:

开发中间件(Middleware)

今天我们来实现一个记录ip 的中间件。

1.新建一个asp.net core项目,选择空的模板。

然后为项目添加一个 Microsoft.Extensions.Logging.Console

NuGet 命令行 ,请使用官方源。

Install-Package Microsoft.Extensions.Logging.Console -Pre

2.新建一个类: 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/

成功运行。

这里我们还可以对这个中间件进行进一步改进,增加更多的功能,如*访问等。

终于知道什么情况下需要实现.NET Core中的IOptions接口

我们所说的ApplicationBuilder是对所有实现了IApplicationBuilder接口的所有类型及其对象的统称。注册到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:}

  • 本文相关:
  • 详解在asp.net core 中使用cookie中间件
  • 详解asp.net core 中间件之压缩、缓存
  • 浅谈asp.net core 中间件详解及项目实战
  • asp.net core 通过中间件防止图片盗链的实例
  • 浅谈asp.net core中间件实现分布式 session
  • 浅谈asp.net core 2.0 带初始参数的中间件(译)
  • asp.net core 2.0 带初始参数的中间件问题及解决方法
  • asp.net core中间件设置教程(7)
  • 如何给asp.net core写个中间件记录接口耗时
  • 根据控件id得到控件并对该控件进行操作
  • asp.net配置kindeditor文本编辑器图文教程
  • asp.net中日历函数calendar的使用方法
  • asp.net mvc-controllerl篇 controllerdescriptor
  • asp.net单选按钮控件radiobutton常用属性和方法介绍
  • asp.net中生成饼状与柱状图实例
  • 用程序修改iis目录的asp.net版本
  • 如此高效通用的分页存储过程是带有sql注入漏洞的zt
  • asp.net button 绑定多个参数
  • .net 缓存模块设计实践
  • net core支持中间件开发吗
  • 终于知道什么情况下需要实现.NET Core中的IOptions接口
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved