ASP.NET MVC随想录——创建自定义的Middleware中间件
经过前2篇文章的介绍,相信大家已经对OWIN和Katana有了基本的了解,那么这篇文章我将继续OWIN和Katana之旅——创建自定义的Middleware中间件。
何为Middleware中间件
Middleware中间件从功能上可以理解为用来处理Http请求,当Server将Http请求封装成符合OWIN规范的字典后,交由Middleware去处理,一般情况下,Pipeline中的Middleware以链式的形式处理Http请求,即每一个Middleware都是最小的模块化,彼此独立、高效。
从语法上理解Middleware的话,他是一个应用程序委托(Func<IDictionary<string, object>, Task>)的实例,通过使用IAppBuilder 接口的Use或者Run方法将一个Middleware插入到Pipeline中,不同的是使用Run方法不需要引用下一个Middleware,即他是Pipeline中最后的处理元素。
使用Inline方式注册Middleware
使用Use方法可以将一个Middleware插入到Pipeline中,值得注意的是需要传入下一个Middleware的引用,代码如下所示:
- app.Use(new Func<Func<IDictionary<string, object>, Task>/*Next*/,
- Func<IDictionary<string, object>/*Environment Dictionary*/, Task>>(next => async env =>
- {
- string before = "Middleware1--Before(inline)"+Environment.NewLine;
- string after = "Middleware1--After(inline)"+Environment.NewLine;
- var response = env["owin.ResponseBody"] as Stream;
- await response.WriteAsync(Encoding.UTF8.GetBytes(before), 0, before.Length);
- await next.Invoke(env);
- await response.WriteAsync(Encoding.UTF8.GetBytes(after), 0, after.Length);
- }));
上述代码中,实例化了一个委托,它需要传入下一个Pipeline中的Middleware引用同时返回一个新的Middleware并插入到Pipeline中。因为是异步的,所以别忘了async、await关键字。
使用Inline+ AppFunc方式注册Middleware
为了简化书写,我为应用程序委托(Func<IDictionary<string, object>, Task>)类型创建了别名AppFunc:
- using AppFunc=Func<IDictionary<string,object>/*Environment Dictionary*/,Task/*Task*/>;
所以又可以使用如下方式来讲Middleware添加到Pipeline中:
- app.Use(new Func<AppFunc, AppFunc>(next => async env =>
- {
- string before = "\tMiddleware2--Before(inline+AppFunc)" + Environment.NewLine;
- string after = "\tMiddleware2--After(inline+AppFunc)" + Environment.NewLine;
- var response = env["owin.ResponseBody"] as Stream;
- await response.WriteAsync(Encoding.UTF8.GetBytes(before), 0, before.Length);
- await next.Invoke(env);
- await response.WriteAsync(Encoding.UTF8.GetBytes(after), 0, after.Length);
- }));
考虑到业务逻辑的增长,有必要将Lambda表达式中的处理逻辑给分离开来,所以对上述代码稍作修改,提取到一个名为Invoke的方法内:
- app.Use(new Func<AppFunc, AppFunc>(next => env => Invoke(next, env)));
- private async Task Invoke(Func<IDictionary<string, object>, Task> next, IDictionary<string, object> env)
- {
- var response = env["owin.ResponseBody"] as Stream;
- string pre = "\t\tMiddleware 3 - Before (inline+AppFunc+Invoke)" + Environment.NewLine;
- string post = "\t\tMiddleware 3 - After (inline+AppFunc+Invoke)" + Environment.NewLine;
- await response.WriteAsync(Encoding.UTF8.GetBytes(pre), 0, pre.Length);
- await next.Invoke(env);
- await response.WriteAsync(Encoding.UTF8.GetBytes(post), 0, post.Length);
- }
虽然将业务逻辑抽取到一个方法中,但Inline这种模式对于复杂的Middleware还是显得不够简洁、易懂。我们更倾向于创建一个单独的类来表示。
定义原生Middleware类的形式来注册Middleware
如果你只想简单的跟踪一下请求,使用Inline也是可行的,但对于复杂的Middleware,我倾向于创建一个单独的类,如下所示:
- public class RawMiddleware
- {
- private readonly AppFunc _next;
- public RawMiddleware(AppFunc next)
- {
- this._next = next;
- }
- public async Task Invoke(IDictionary<string,object> env )
- {
- var response = env["owin.ResponseBody"] as Stream;
- string pre = "\t\t\tMiddleware 4 - Before (RawMiddleware)" + Environment.NewLine;
- string post = "\t\t\tMiddleware 4 - After (RawMiddleware)\r\n" + Environment.NewLine;
- await response.WriteAsync(Encoding.UTF8.GetBytes(pre), 0, pre.Length);
- await _next.Invoke(env);
- await response.WriteAsync(Encoding.UTF8.GetBytes(post), 0, post.Length);
- }
- }
最后,依旧是通过Use方法来将Middleware添加到Pipeline中:
- //两者方式皆可
- //app.Use<RawMiddleware>();
- app.Use(typeof (RawMiddleware));
上述代码中,IAppBuilder实例的Use方法添加Middleware至Pipeline与Inline方式有很大不同,它接受一个Type而非Lambda表达式。在这种情形下,创建了一个Middleware类型的实例,并将Pipeline中下一个Middleware传递到构造函数中,最后当Middleware被执行时调用Invoke方法。
注意Middleware是基于约定的形式定义的,需要满足如下条件:
- 构造函数的第一个参数必须是Pipeline中下一个Middleware
- 必须包含一个Invoke方法,它接收Owin环境字典,并返回Task
使用Katana Helper来注册Middleware
程序集Microsoft.Owin包含了Katana为我们提供的Helper,通过他,可以简化我们的开发,比如IOwinContext封装了Owin的环境字典,强类型对象可以通过属性的形式获取相关数据,同时为IAppBuilder提供了丰富的扩展方法来简化Middleware的注册,如下所示:
- app.Use(async (context, next) =>
- {
- await context.Response.WriteAsync("\t\t\t\tMiddleware 5--Befone(inline+katana helper)"+Environment.NewLine);
- await next();
- await context.Response.WriteAsync("\t\t\t\tMiddleware 5--After(inline+katana helper)"+Environment.NewLine);
- });
当然我们也可以定义一个Middleware类并继承OwinMiddleware,如下所示:
- public class MyMiddleware : OwinMiddleware
- {
- public MyMiddleware(OwinMiddleware next)
- : base(next)
- {
- }
- public override async Task Invoke(IOwinContext context)
- {
- await context.Response.WriteAsync("\t\t\t\t\tMiddleware 6 - Before (Katana helped middleware class)"+Environment.NewLine);
- await this.Next.Invoke(context);
- await context.Response.WriteAsync("\t\t\t\t\tMiddleware 6 - After (Katana helped middleware class)"+Environment.NewLine);
- }
- }
然后将其添加到Pipeline中:
- app.Use<MyMiddleware>();
Middleware的执行顺序
在完成上面Middleware注册之后,在Configuration方法的最后添加最后一个的Middleware中间件,注意它并不需要对下一个Middleware的引用了,我们可以使用Run方法来完成注册:
- app.Run(context => context.Response.WriteAsync("\t\t\t\t\t\tHello World"+Environment.NewLine));
值得注意的是,Pipeline中Middleware处理Http Request顺序同注册顺序保持一致,即和Configuration方法中书写的顺序保持一致,Response顺序则正好相反,如下图所示:
最后,运行程序,查看具体的输出结果是否和我们分析的保持一致:
小结
在这篇文章中,我为大家讲解了自定义Middleware的创建,Katana为我们提供了非常多的方式来创建和注册Middleware,在下一篇文章中,我将继续OWIN和Katana之旅,探索Katana和其他Web Framework的集成。
转载于:https://www.cnblogs.com/OceanEyes/p/thinking-in-asp-net-mvc-create-custom-middleware.html
ASP.NET MVC随想录——创建自定义的Middleware中间件相关推荐
- middlewareserver_创建自定义的Middleware中间件
经过前2篇文章的介绍,相信大家已经对OWIN和Katana有了基本的了解,那么这篇文章我将继续OWIN和Katana之旅--创建自定义的Middleware中间件. 何为Middleware中间件 M ...
- 在 ASP.NET MVC 中创建自定义 HtmlHelper
在ASP.NET MVC应用程序的开发中,我们常碰到类似Html.Label或Html.TextBox这样的代码,它将在网页上产生一个label或input标记.这些HtmlHelper的扩展方法有些 ...
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需要将相应的ValidationAttri ...
- 如何在ASP.NET Core中创建自定义AuthorizeAttribute?
本文翻译自:How do you create a custom AuthorizeAttribute in ASP.NET Core? I'm trying to make a custom aut ...
- 3分钟学会在 ASP.NET MVC 中创建、读取和编辑 Excel 电子表格
在本文中,您将学习如何在ASP.NET MVC 应用程序中创建.读取和编辑 Excel 电子表格.为此,我们将创建一个由功能丰富的网格控件组成的电子表格应用程序,用于显示和编辑 Excel 文件,如下 ...
- ASP.NET Core 配置 - 创建自定义配置提供程序
ASP.NET Core 配置 - 创建自定义配置提供程序 在本文中,我们将创建一个自定义配置提供程序,从数据库读取我们的配置.我们已经了解了默认配置提供程序的工作方式,现在我们将实现我们自己的自定义 ...
- ASP.NET MVC随想录——漫谈OWIN
什么是OWIN OWIN是Open Web Server Interface for .NET的首字母缩写,他的定义如下: OWIN在.NET Web Servers与Web Application之 ...
- [转]利用ASP.NET 2.0创建自定义Web控件(1)
原址:http://hi.baidu.com/sjbh/blog/item/cc58fd1bd35d3ad2ad6e7593.html 简介 从使用基本的文本编辑器到创作标记页面,Web 开发已经 ...
- 在ASP.NET Core中创建自定义端点可视化图
在上篇文章中,我为构建自定义端点可视化图奠定了基础,正如我在第一篇文章中展示的那样.该图显示了端点路由的不同部分:文字值,参数,动词约束和产生结果的端点: 在本文中,我将展示如何通过创建一个自定义的D ...
最新文章
- java 高级数据类型_【高级数据类型】- 2.通道的更多种类
- redis windows版本的使用
- The Road to Ryu: Hi Ryu
- Nginx的upstream_response_time
- 如何解决复杂条件下的程序流的控制问题?
- html5中音乐播放器怎么写,打造属于自己的音乐播放器 HTML5之audio标签
- 简单技能之程序调试入门
- java jdom进行xml的增删改差_java使用DOM对XML文档进行增删改查操作实例代码
- APACHE局域网配置域名访问
- 浅议“全局变量”、“多线程”和“编译器陷阱”
- Java数组– java.util.Arrays
- 编程珠玑第一章习题解答
- 微信跳转,wap浏览器跳转到微信
- COMS门电路的设计及其优化--以异或门为例
- .Net Web微信H5鱼虾蟹网站开发搭建技术栈
- Word和WPS中引入Mathtype的常见问题
- [DB][mysql]下出现 java.sql.SQLException: Incorrect string value: '\xF4\x80\x8E\xAE\xE8\x83...'
- 为什么叫Windows 7?
- ubuntu10.04安装有线网卡驱动
- CSS中使用的一些颜色代码
热门文章
- SpringBoot自定义MessageConverter
- STM32开发 -- 地球坐标系(WGS84),火星坐标系(GCJ02), 百度坐标系(BD09)坐标转换
- Hi3516A开发--目录分析
- 状态管理 界面数据信息
- 百斗度输入法linux,斗字输入法安卓版-斗字输入法app下载-最火软件站
- 跨链资产原子转移工具包 Decred atomicswap
- 农民斗地主——Binder fuzz安全研究
- 合作模式歌利亚机器人_智能时代挑战下的机器人教育新方向!
- resultset rs =pst.executequery();发生异常_07795.14.4HMaster无法成为Active异常分析
- android 缩略图uri_课题_android系统通过图片绝对路径获取URI的三种方法