熟悉ASP.NET架构的开发者一定对于HTTP Modules与HTTP Handlers不陌生。两者的作用主要是对网络请求执行特定的处理工作。而在.NET Core中,它们都被Middleware(中件间)取代了。

之前的Http Modules和HTTP Handlers是如下图般处理请求的:

现在变成了这样:

一言概括之,Middleware完成了HTTP Modules与HTTP Handlers的原有工作,但又不是简单的化二为一的减法作用。

Middleware减去的其实是与原来ASP.NET中重要的基础——应用程序生命周期事件(application life cycle event)的绑定。

HTTP Modules在初始化时就需要针对HttpApplication的事件作绑定处理,这样当HttpApplication的各项事件被触发时,已绑定的相应处理程序才会按照预期的那样被执行。

  1. public class HelloWorldModule : IHttpModule
  2. {
  3. public HelloWorldModule()
  4. {
  5. }
  6. public String ModuleName
  7. {
  8. get { return "HelloWorldModule"; }
  9. }
  10. // In the Init function, register for HttpApplication
  11. // events by adding your handlers.
  12. public void Init(HttpApplication application)
  13. {
  14. application.BeginRequest +=
  15. (new EventHandler(this.Application_BeginRequest));
  16. application.EndRequest +=
  17. (new EventHandler(this.Application_EndRequest));
  18. }
  19. private void Application_BeginRequest(Object source,
  20. EventArgs e)
  21. {
  22. // Create HttpApplication and HttpContext objects to access
  23. // request and response properties.
  24. HttpApplication application = (HttpApplication)source;
  25. HttpContext context = application.Context;
  26. context.Response.Write("<h1><font color=red>
  27. HelloWorldModule: Beginning of Request
  28. </font></h1><hr>");
  29. }
  30. private void Application_EndRequest(Object source, EventArgs e)
  31. {
  32. HttpApplication application = (HttpApplication)source;
  33. HttpContext context = application.Context;
  34. context.Response.Write("<hr><h1><font color=red>
  35. HelloWorldModule: End of Request</font></h1>");
  36. }
  37. public void Dispose()
  38. {
  39. }
  40. }

然后你还需要在web.config配置文件注册这个HTTP Module。

  1. <configuration>
  2. <system.web>
  3. <httpModules>
  4. <add name="HelloWorldModule" type="HelloWorldModule"/>
  5. </httpModules>
  6. </system.web>
  7. </configuration>

如果是用Middleware的话,事情就变得很简单了。抛弃IHttpModule接口及HttpModule实现类,不用再关心HttpApplication的任何事件,还有烦人的web.config配置。直接在代码中以最简洁的方式完成工作。


  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. app.Use(async(context, next) =>{
  4. await context.Response.WriteAsync("Beginning of Request\n");
  5. await next.Invoke();
  6. await context.Response.WriteAsync("End of Request\n");
  7. });
  8. app.Run(async (context) =>
  9. {
  10. await context.Response.WriteAsync("Hello World!\n");
  11. });
  12. }

相似的,对于HTTP Handlers,虽然不用取消对HttpApplication事件的依赖,但以两者的代码实现方式作比较,Middleware亳无疑问胜出一筹。

  1. public class HelloWorldHandler : IHttpHandler
  2. {
  3. public HelloWorldHandler()
  4. {
  5. }
  6. public void ProcessRequest(HttpContext context)
  7. {
  8. HttpRequest Request = context.Request;
  9. HttpResponse Response = context.Response;
  10. // This handler is called whenever a file ending
  11. // in .sample is requested. A file with that extension
  12. // does not need to exist.
  13. Response.Write("<html>");
  14. Response.Write("<body>");
  15. Response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>");
  16. Response.Write("</body>");
  17. Response.Write("</html>");
  18. }
  19. public bool IsReusable
  20. {
  21. // To enable pooling, return true here.
  22. // This keeps the handler in memory.
  23. get { return false; }
  24. }
  25. }

仍需要在web.config文件中注册HTTP handler。

  1. <configuration>
  2. <system.web>
  3. <httpHandlers>
  4. <add verb="*" path="*.sample"
  5. type="HelloWorldHandler"/>
  6. </httpHandlers>
  7. </system.web>
  8. </configuration>

换作Middleware的写法:

  1. private static void HandleSample(IApplicationBuilder app)
  2. {
  3. app.Run(async context =>
  4. {
  5. await context.Response.WriteAsync("Hello Sample");
  6. });
  7. }
  8. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  9. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  10. {
  11. app.MapWhen(context => context.Request.Path.Value.EndsWith("sample"), HandleSample);
  12. }

总结下使用Middleware的优点:

  • 没有对HttpApplication的依赖
  • 没有对IHttpModule与IHttpHandler接口的依赖
  • 无需在web.config文件中添加各种配置
  • 代码简洁

最后需要补充Middleware与HTTP Modules的一点差异。各Middleware中处理请求与响应的顺序是刚好相反的,越早处理请求的Middleware越晚处理响应。而HTTP Modules中处理请求与响应的顺序则保持一致,因为每个HTTP Module请求与响应事件的绑定都是在同一阶段完成的。

.NET Core开发日志——Middleware的更多相关文章

  1. .NET Core开发日志——RequestDelegate

    本文主要是对.NET Core开发日志--Middleware的补遗,但是会从看起来平平无奇的RequestDelegate开始叙述,所以以其作为标题,也是合情合理. RequestDelegate是 ...

  2. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  3. .NET Core开发日志——Entity Framework与PostgreSQL

    Entity Framework在.NET Core中被命名为Entity Framework Core.虽然一般会用于对SQL Server数据库进行数据操作,但其实它还支持其它数据库,这里就以Po ...

  4. ASP.NET Core 开发-中间件(Middleware)

    ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...

  5. .NET Core开发日志——从搭建开发环境开始

    .NET Core自2016年推出1.0版本开始,到目前已是2.1版本,在其roadmap计划里明年更会推出3.0版本,发展不可不谓之迅捷.不少公司在经过一个谨慎的观望期后,也逐步开始将系统升级至最新 ...

  6. .NET Core开发日志——简述路由

    有过ASP.NET或其它现代Web框架开发经历的开发者对路由这一名字应该不陌生.如果要用一句话解释什么是路由,可以这样形容:通过对URL的解析,指定相应的处理程序. 回忆下在Web Forms应用程序 ...

  7. .NET Core开发日志——GraphQL

    GraphQL是什么 GraphQL既是一种用于API的查询语言也是一种通过使用对应数据的类型系统,执行数据查询的服务端运行时.GraphQL没有局限于任何数据库或存储引擎,而是通过既有代码及数据获得 ...

  8. .NET Core开发日志——结构化日志

    在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net.而其后来者,莫过于NLog.Nlog与log4net相比,有一项较显著的优势,它支持结构化日志. 结 ...

  9. .NET Core开发日志——Edge.js

    最近在项目中遇到这样的需求:要将旧有系统的一部分业务逻辑集成到新的自动化流程工具中.这套正在开发的自动化工具使用的是C#语言,而旧有系统的业务逻辑则是使用AngularJS在前端构建而成.所以最初的考 ...

随机推荐

  1. Bullet物理引擎的安装与使用

    图形赋予游戏一种视觉的吸引力,但是能够让游戏的世界鲜活起来的还应该是内部的物理引擎.物理引擎是游戏引擎中的子模块,是一种软件组件,可仿真物理系统.它根据牛顿力学定律,计算游戏中物体的合理的物理位置,并 ...

  2. [Aaronyang紫色博客] 写给自己的WPF4.5-Blend5公开课系列 1

     我的文章一定要做到对读者负责,否则就是失败的文章  ---------   www.ayjs.net    aaronyang技术分享 欢迎大家支持我的力作<[Aaronyang] 写给自己的 ...

  3. .so.x不是符号连接

    去到这个目录下查看,会发现有多个.so.x文件.x是版本号的区别.将它们动态软连接在一起就可以了 参考这个博客

  4. [转]Object.keys()和for in的排序问题

    原文地址:https://www.jianshu.com/p/a086ff48be6e Object.keys()和for in 具有相同的排列顺序 如果属性名的类型是Number,那么Object. ...

  5. 【Unity】讯飞语音识别SDK

    1.进入讯飞官网,注册帐号,进入控制台,创建新应用UnityXunfeiDemo,平台选Android.在当前应用这点下载SDK,添加AI能力(添加新服务),选择语音听写,即可下载安卓SDK(下称讯飞 ...

  6. Spring Security 认证流程

    请求之间共享SecurityContext原因:

  7. Linux(C/C++)下的文件操作open、fopen与freopen

    open是linux下的底层系统调用函数, fopen与freopen c/c++下的标准I/O库函数,带输入/输出缓冲. linxu下的fopen是open的封装函数,fopen最终还是要调用底层的 ...

  8. debian系列下c++调用mysql, linux下面安装mysql.h文件

    mysql.h的报错还没有解决,你们不用看了,等我解决了吧还不知道什么时候 先用c吧 #include <stdio.h> #include <stdlib.h> #inclu ...

  9. SAP项目的整体预算大概是多少?

    例如一家规模包括(5-6个生产型子公司),员工5000人,市值100亿,销售额每年20亿左右的集团公司.上SAP,预算怎么算? 这其中:1)软件费用一般多少? 2)用户费用是怎么算的? 3)维护费用又 ...

  10. Docker孵化的5个开源项目

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/81977243 回想过去短短 ...