熟悉ASP.NET架構的開發者必定對於HTTP Modules與HTTP Handlers不陌生。二者的做用主要是對網絡請求執行特定的處理工做。而在.NET Core中,它們都被Middleware(中件間)取代了。html
以前的Http Modules和HTTP Handlers是以下圖般處理請求的:web
如今變成了這樣:網絡
一言歸納之,Middleware完成了HTTP Modules與HTTP Handlers的原有工做,但又不是簡單的化二爲一的減法做用。架構
Middleware減去的實際上是與原來ASP.NET中重要的基礎——應用程序生命週期事件(application life cycle event)的綁定。app
HTTP Modules在初始化時就須要針對HttpApplication的事件做綁定處理,這樣當HttpApplication的各項事件被觸發時,已綁定的相應處理程序纔會按照預期的那樣被執行。async
public class HelloWorldModule : IHttpModule { public HelloWorldModule() { } public String ModuleName { get { return "HelloWorldModule"; } } // In the Init function, register for HttpApplication // events by adding your handlers. public void Init(HttpApplication application) { application.BeginRequest += (new EventHandler(this.Application_BeginRequest)); application.EndRequest += (new EventHandler(this.Application_EndRequest)); } private void Application_BeginRequest(Object source, EventArgs e) { // Create HttpApplication and HttpContext objects to access // request and response properties. HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<h1><font color=red> HelloWorldModule: Beginning of Request </font></h1><hr>"); } private void Application_EndRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<hr><h1><font color=red> HelloWorldModule: End of Request</font></h1>"); } public void Dispose() { } }
而後你還須要在web.config配置文件註冊這個HTTP Module。ui
<configuration> <system.web> <httpModules> <add name="HelloWorldModule" type="HelloWorldModule"/> </httpModules> </system.web> </configuration>
若是是用Middleware的話,事情就變得很簡單了。拋棄IHttpModule接口及HttpModule實現類,不用再關心HttpApplication的任何事件,還有煩人的web.config配置。直接在代碼中以最簡潔的方式完成工做。this
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Use(async(context, next) =>{ await context.Response.WriteAsync("Beginning of Request\n"); await next.Invoke(); await context.Response.WriteAsync("End of Request\n"); }); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!\n"); }); }
類似的,對於HTTP Handlers,雖然不用取消對HttpApplication事件的依賴,但以二者的代碼實現方式做比較,Middleware亳無疑問勝出一籌。3d
public class HelloWorldHandler : IHttpHandler { public HelloWorldHandler() { } public void ProcessRequest(HttpContext context) { HttpRequest Request = context.Request; HttpResponse Response = context.Response; // This handler is called whenever a file ending // in .sample is requested. A file with that extension // does not need to exist. Response.Write("<html>"); Response.Write("<body>"); Response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>"); Response.Write("</body>"); Response.Write("</html>"); } public bool IsReusable { // To enable pooling, return true here. // This keeps the handler in memory. get { return false; } } }
仍須要在web.config文件中註冊HTTP handler。code
<configuration> <system.web> <httpHandlers> <add verb="*" path="*.sample" type="HelloWorldHandler"/> </httpHandlers> </system.web> </configuration>
換做Middleware的寫法:
private static void HandleSample(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Hello Sample"); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.MapWhen(context => context.Request.Path.Value.EndsWith("sample"), HandleSample); }
總結下使用Middleware的優勢:
最後須要補充Middleware與HTTP Modules的一點差別。各Middleware中處理請求與響應的順序是恰好相反的,越早處理請求的Middleware越晚處理響應。而HTTP Modules中處理請求與響應的順序則保持一致,由於每一個HTTP Module請求與響應事件的綁定都是在同一階段完成的。