亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

解讀ASP.NET 5 & MVC6系列(6):Middleware詳解

2019-11-17 02:06:22
字體:
來源:轉載
供稿:網友

解讀asp.net 5 & MVC6系列(6):Middleware詳解

2015-05-19 09:16 by 湯姆大叔, ... 閱讀, ... 評論, 收藏, 編輯

在第1章項目結構分析中,我們提到Startup.cs作為整個程序的入口點,等同于傳統的Global.asax文件,即:用于初始化系統級的信息(例如,MVC中的路由配置)。本章我們就來一一分析,在這里如何初始化這些系統級的信息。

新舊版本之間的Pipeline區別

ASP.NET 5和之前版本的最大區別是對HTTP Pipeline的全新重寫,在之前的版本中,請求過濾器的通常是以HttpModule為模塊組件,這些組件針對Httpapplication里定義的各個周期內的事件進行響應,從而用于實現認證、全局錯誤處理、日志等功能。傳統的Form表單認證就是一個HTTPModule。HTTPModule不僅能夠過濾Request請求,還可以和Response響應進行交互并修改。這些HTTPModule組件都繼承于IHttpModule接口,而該接口是位于System.Web.dll中。

HttpModule代碼不僅可以在Global.asax中的各事件周期中進行添加,還可以單獨編譯成類庫并在web.config中進行注冊。

新版的ASP.NET 5拋棄了重量級的System.Web.dll,相應地引入了Middleware的概念,Middleware的官方定義如下:

Pass through components that form a pipeline between a server and application to inspect, route, or modify request and response messages for a specific purpose.在服務器和應用程序之間的管線Pipeline之間,針對特定的目的,穿插多個Middleware組件,從而對request請求和response響應進行檢查、路由、或修改。

該定義和傳統的HttpModule以及HttpHandler特別像。

Middleware的注冊和配置

在ASP.NET5中,request請求管線(Pipeline)的訪問是在Startup類中進行的,該類時一個約定類,并且里面的ConfigureServices方法、Configure方法、以及相應的參數也是事先約定的,所以不能進行改動。

Middleware中的依賴處理:ConfigureServices方法

在ASP.NET5中的各種默認的Middleware中,都使用了依賴注入的功能,所以在使用Middleware中的功能時,需要提前將依賴注入所需要的類型及映射關系都注冊到依賴注入管理系統中,即IServiceCollection集合,而ConfigureServices方法接收的就一個IServiceCollection類型的參數,該參數就是所有注冊過類型的集合,通過原生的依賴注入組件進行管理(關于ASP.NET5中的依賴注入,我們會在單獨章節中進行講解),在該方法內,我們可以向該集合中添加新的類型和類型映射關系,示例如下:

// Add MVC services to the services container.services.AddMvc();

示例中的代碼用于向系統添加Mvc模塊相關的Service類型以支撐MVC功能,該方法是一個擴展方法,用于在集合中添加與MVC相關的多個類型。

Middleware的注冊和配置:Configure方法

Configure方法的簽名如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory){    // ...}

Configure方法接收了三個參數:IApplicationBuilder類型的參數用于構建整個應用程序的配置信息,IHostingEnvironment類的env參數用于訪問系統環境變量相關的內容,ILoggerFactory類型的loggerfactory用于日志相關的內容處理,其中IApplicationBuilder類型的參數最為重要,該參數實例app上有一系列的擴展方法用于將各種Middleware注冊到request請求管線(Pipeline)中。這種方式和之前ASP.NET中的HTTP管線的主要區別是:新版本中的組合模型替換了舊版本中的事件模型。這也就要求,在新版ASP.NET中,Middleware組件注冊的順序是非常重要的,因為后一個組件可能要使用到前一個組件,所以必須按照依賴的先后順序進行注冊,舉例如下,當前MVC項目的模板代碼示例如下:

// Add static files to the request pipeline.app.UseStaticFiles();// Add cookie-based authentication to the request pipeline.app.UseIdentity();// Add MVC to the request pipeline.app.UseMvc(routes =>{ /*...*/});

示例中的UseStaticFilesUseIdentity、UseMvc都是IApplicationBuilder上的擴展方法,在擴展方法中,都會通過調用擴展方法app.UseMiddleware方法,最終再調用app.Use方法來注冊新的Middleware,該方法定義如下:

public interface IApplicationBuilder{    //...    IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);}

通過代碼,可以看出,middleware是Func<RequestDelegate, RequestDelegate>的一個實例,該Func接收一個RequestDelegate的參數,并返回一個RequestDelegate類型的值。RequestDelegate源碼如下:

public delegate Task RequestDelegate(HttpContext context);

通過源碼,我們可以看出,RequestDelegate是一個委托函數,其接收HttpContext類型的實例,并返回一個Task類型的異步對象。也就是說RequestDelegate是一個可以返回自身RequestDelegate類型函數的函數,整個ASP.NET也就是利用這種方式構建了管線(Pipelien)的組成,在這里,每個middleware都鏈式到下一個middleware上,并在整個過程中可以對HttpConext對象進行修改或維護,當然,HttpContext中就包括了我們常操作的HttPRequestHttpResponse實例對象。

注意:HttpContext、HttpRequestHttpResponse在ASP.NET 5中都是重新定義的新類型。

Middleware的定義

既然每個middleare都是Func<RequestDelegate, RequestDelegate>的一個實例,那是不是Middleware的定義要滿足一個規則?是繼承于一個抽象基類還是借口?通過翻查相關的代碼,我們看到,Middleware是基于約定的形式來定義的,具體約定規則如下:

  1. 構造函數的第一個參數必須是處理管線中的下一個處理函數,即RequestDelegate;
  2. 必須有一個 Invoke 函數, 并接受上下文參數(即HttpContent), 然后返回 Task;

示例如下:

public class MiddlewareName{    RequestDelegate _next;    public MiddlewareName(RequestDelegate next)    {        _next = next;// 接收傳入的RequestDelegate實例    }    public async Task Invoke(HttpContext context)    {        // 處理代碼,如處理context.Request中的內容        Console.WriteLine("Middleware開始處理");        await _next(context);        Console.WriteLine("Middleware結束處理");        // 處理代碼,如處理context.Response中的內容    }}

通過該模板代碼可以看到,首先一個Middleware的構造函數要接收一個RequestDelegate的實例,先保存在一個私有變量里,然后通過調用Invoke方法(并接收HttpContent實例)并返回一個Task,并且在調用Invoke的方法中,要通過await _next(context);語句,鏈式到下一個Middleware上,我們的處理代碼主要就是在鏈式語句的前后執行相關的代碼。

舉個例子,如果我們要想記錄頁面的執行時間,首先,我們先定義一個TimeRecorderMiddleware,代碼如下:

public class TimeRecorderMiddleware{    RequestDelegate _next;    public TimeRecorderMiddleware(RequestDelegate next)    {        _next = next;    }    public async Task Invoke(HttpContext context)    {        var sw = new Stopwatch();        sw.Start();        await _next(context);        var newDiv = @"<div id=""process"">頁面處理時間:{0} 毫秒</div></body>";        var text = string.Format(newDiv, sw.ElapsedMilliseconds);        await context.Response.WriteAsync(text);    }}

Middleware的注冊有很多種方式,如下是實例型注冊代碼:

app.Use(next => new TimeRecorderMiddleware(next).Invoke);

或者,你也可以使用UseMiddleware擴展方法進行注冊,示例如下:

app.UseMiddleware<TimeRecorderMiddleware>();//app.UseMiddleware(typeof(TimeRecorderMiddleware)); 兩種方式都可以

當然,你也可以定義一個自己的擴展方法用于注冊該Middleware,代碼如下:

public static IApplicationBuilder UseTimeRecorderMiddleware(this IApplicationBuilder app){    return app.UseMiddleware<TimeRecorderMiddleware>();}

最后在Startup類的Configure方法內進行注冊,代碼如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory){    app.UseTimeRecorderMiddleware(); // 要放在前面,以便進行統計,如果放在Mvc后面的話,就統計不了時間了。    // 等等}

編譯,重啟,并訪問頁面,在頁面的底部即可看到頁面的運行時間提示內容。

常用Middleware功能的使用

app.UseErrorPage() 在IHostingEnvironment.EnvironmentName為Development的情況下,才顯示錯誤信息,并且錯誤信息的顯示種類,可以通過額外的ErrorPageOptions參數來設定,可以設置全部顯示,也可以設置只顯示Cookies、Environment、ExceptionDetails、Headers、Query、SourceCode SourceCodeLineCount中的一種或多種。

app.UseErrorHandler("/Home/Error") 捕獲所有的程序異常錯誤,并將請求跳轉至指定的頁面,以達到友好提示的目的。

app.UseStaticFiles() 開啟靜態文件也能走該Pipeline管線處理流程的功能。

app.UseIdentity() 開啟以cookie為基礎的ASP.NET identity認證功能,以支持Pipeline請求處理。

直接使用委托定義Middleware的功能

由于Middleware是Func<RequestDelegate, RequestDelegate>委托類型的實例,所以我們也可以不必定義一個單獨的類,在Startup類里,使用委托調用的方式就可以了,示例如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory){   app.Use(new Func<RequestDelegate, RequestDelegate>(next => content => Invoke(next, content)));   // 其它}// 注意Invoke方法的參數private async Task Invoke(RequestDelegate next, HttpContext content){   Console.WriteLine("初始化組件開始");   await next.Invoke(content);   Console.WriteLine("管道下步執行完畢");}

做個簡便的Middleware基類

雖然有約定方法,但有時候我們在開發的時候往往會犯迷糊,想不起來到底是什么樣的約定,所以,在這里我們可以定義一個抽象基類,然后以后所有的Middleware在定義的時候都繼承該抽象類并重載Invoke方法即可,從而可以避免約定忘記的問題。代碼如下:

/// <summary>/// 抽象基類/// </summary>public abstract class Abst
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色综合91久久精品中文字幕| 久久天天躁狠狠躁夜夜躁2014| 亚洲理论电影网| 国模精品视频一区二区| 欧美一区二区三区图| 久久国产视频网站| 日韩av免费看| 91午夜理伦私人影院| 日韩精品中文字幕在线观看| 成人网在线免费看| 日韩欧美中文第一页| 国产精品亚洲аv天堂网| 亚洲人成电影在线观看天堂色| 国产一区二区三区丝袜| 欧美性videos高清精品| 日韩精品福利网站| 国产精品美女久久久久久免费| 中文字幕在线观看日韩| 日本久久久久亚洲中字幕| 亚洲最大福利网| 亚洲国语精品自产拍在线观看| 国产精品久久久久久久久免费看| 成人精品一区二区三区电影黑人| 欧美成人亚洲成人| 欧美精品videossex88| 精品国产一区av| 成人中文字幕在线观看| 亚洲人成五月天| 国产精品久久久久久久久免费| 亚洲欧美激情在线视频| 欧美极品少妇全裸体| 91在线无精精品一区二区| 久久不射热爱视频精品| 亚洲国产中文字幕在线观看| 久久这里有精品视频| 国产91精品久久久| 国产美女高潮久久白浆| 国产主播在线一区| 国产精品视频男人的天堂| 黄色91在线观看| 欧洲精品毛片网站| 欧美一级高清免费播放| 精品女同一区二区三区在线播放| 热久久免费国产视频| 国产亚洲美女精品久久久| 成人精品一区二区三区| 国产日韩欧美自拍| 欧美性猛交xxxxx免费看| 久久成人av网站| 久久综合国产精品台湾中文娱乐网| 欧美成人免费全部| 日韩精品免费看| 欧美黄色小视频| 精品视频久久久久久久| 久久夜精品香蕉| 欧美黑人一区二区三区| 日韩精品在线视频| 精品久久久久久亚洲精品| 国产精品欧美日韩久久| 亚洲va欧美va在线观看| 欧美一级免费视频| 亚洲国产精品美女| 亚洲日本成人女熟在线观看| 久热99视频在线观看| 亚洲精品一区二三区不卡| 欧美猛交ⅹxxx乱大交视频| 成人妇女淫片aaaa视频| 欧美老少配视频| 中文字幕日韩在线播放| 亚洲一区二区久久久久久| 亚洲国产精品一区二区久| 亚洲亚裔videos黑人hd| 欧美综合国产精品久久丁香| 伊人久久久久久久久久| 亚洲人精选亚洲人成在线| 精品亚洲精品福利线在观看| 国产精品精品久久久久久| 久久久久久久影视| 久久免费视频在线| 国产精品久久久久久久一区探花| 国产视频在线一区二区| 深夜福利日韩在线看| 色婷婷综合久久久久| 91国内产香蕉| 亚洲人成电影在线观看天堂色| 91久久精品日日躁夜夜躁国产| 日韩在线激情视频| 国产欧美在线观看| 亚洲色图综合网| 日本精品视频在线观看| 国产在线98福利播放视频| 国产福利精品av综合导导航| 91欧美精品午夜性色福利在线| 91影院在线免费观看视频| 91精品国产综合久久香蕉的用户体验| 69av视频在线播放| 久久成人一区二区| 国产欧美日韩专区发布| 欧美精品成人在线| 91久久精品美女| 欧美精品videos| 久久99视频免费| 欧美成人一二三| 欧美成在线观看| 国产精品一区二区3区| 亚洲欧美在线一区二区| 久久久这里只有精品视频| 92看片淫黄大片欧美看国产片| 日韩在线中文视频| 欧美色图在线视频| 亚洲成人激情在线观看| 91亚洲精品久久久久久久久久久久| 一本大道久久加勒比香蕉| 久久99久久99精品免观看粉嫩| 国产免费一区二区三区在线能观看| 97在线免费视频| 另类少妇人与禽zozz0性伦| 国产成人在线亚洲欧美| 久操成人在线视频| 久久免费精品视频| 91老司机在线| 国产午夜精品全部视频在线播放| 92版电视剧仙鹤神针在线观看| 亚洲日韩中文字幕| 亚洲欧美日韩国产中文| 亚洲偷欧美偷国内偷| 国产精品久久久久久久一区探花| 国产精品69精品一区二区三区| 亚洲性线免费观看视频成熟| 国产成人精品综合久久久| 国产精品电影久久久久电影网| 国产精品视频xxxx| 日本一区二区在线免费播放| 一区二区三区久久精品| 成人写真视频福利网| 有码中文亚洲精品| 久久国产精品久久精品| 国产91精品久久久久久久| 5252色成人免费视频| 亚洲午夜小视频| 一区二区三区久久精品| 午夜精品免费视频| 激情成人在线视频| 黄色成人av在线| 国产精品专区h在线观看| 日韩av最新在线观看| 亚洲精品电影在线| 国产有码一区二区| 国产在线观看一区二区三区| 色老头一区二区三区| 成人激情视频小说免费下载| 久99九色视频在线观看| 精品成人乱色一区二区| 欧美一级大片在线观看| 欧美激情视频一区二区三区不卡| 91热精品视频| 96精品久久久久中文字幕| 亚洲一区二区三区xxx视频| 国产丝袜视频一区| 一本大道亚洲视频| 久久久久久久久国产精品| 国产一区二区三区久久精品| 亚洲韩国欧洲国产日产av| 亚洲国产中文字幕久久网|