国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

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

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:37:02
文檔

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

解讀ASP.NET 5 & MVC6系列教程(6):Middleware詳解:在第1章項(xiàng)目結(jié)構(gòu)分析中,我們提到Startup.cs作為整個(gè)程序的入口點(diǎn),等同于傳統(tǒng)的Global.asax文件,即:用于初始化系統(tǒng)級(jí)的信息(例如,MVC中的路由配置)。本章我們就來(lái)一一分析,在這里如何初始化這些系統(tǒng)級(jí)的信息。 新舊版本之間的Pipeline區(qū)別 A
推薦度:
導(dǎo)讀解讀ASP.NET 5 & MVC6系列教程(6):Middleware詳解:在第1章項(xiàng)目結(jié)構(gòu)分析中,我們提到Startup.cs作為整個(gè)程序的入口點(diǎn),等同于傳統(tǒng)的Global.asax文件,即:用于初始化系統(tǒng)級(jí)的信息(例如,MVC中的路由配置)。本章我們就來(lái)一一分析,在這里如何初始化這些系統(tǒng)級(jí)的信息。 新舊版本之間的Pipeline區(qū)別 A

在第1章項(xiàng)目結(jié)構(gòu)分析中,我們提到Startup.cs作為整個(gè)程序的入口點(diǎn),等同于傳統(tǒng)的Global.asax文件,即:用于初始化系統(tǒng)級(jí)的信息(例如,MVC中的路由配置)。本章我們就來(lái)一一分析,在這里如何初始化這些系統(tǒng)級(jí)的信息。

新舊版本之間的Pipeline區(qū)別

ASP.NET 5和之前版本的最大區(qū)別是對(duì)HTTP Pipeline的全新重寫,在之前的版本中,請(qǐng)求過(guò)濾器的通常是以HttpModule為模塊組件,這些組件針對(duì)HttpApplication里定義的各個(gè)周期內(nèi)的事件進(jìn)行響應(yīng),從而用于實(shí)現(xiàn)認(rèn)證、全局錯(cuò)誤處理、日志等功能。傳統(tǒng)的Form表單認(rèn)證就是一個(gè)HTTPModuleHTTPModule不僅能夠過(guò)濾Request請(qǐng)求,還可以和Response響應(yīng)進(jìn)行交互并修改。這些HTTPModule組件都繼承于IHttpModule接口,而該接口是位于System.Web.dll中。

HttpModule代碼不僅可以在Global.asax中的各事件周期中進(jìn)行添加,還可以單獨(dú)編譯成類庫(kù)并在web.config中進(jìn)行注冊(cè)。

新版的ASP.NET 5拋棄了重量級(jí)的System.Web.dll,相應(yīng)地引入了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.
在服務(wù)器和應(yīng)用程序之間的管線Pipeline之間,針對(duì)特定的目的,穿插多個(gè)Middleware組件,從而對(duì)request請(qǐng)求和response響應(yīng)進(jìn)行檢
查、路由、或修改。

該定義和傳統(tǒng)的HttpModule以及HttpHandler特別像。

Middleware的注冊(cè)和配置

在ASP.NET5中,request請(qǐng)求管線(Pipeline)的訪問(wèn)是在Startup類中進(jìn)行的,該類時(shí)一個(gè)約定類,并且里面的ConfigureServices方法、Configure方法、以及相應(yīng)的參數(shù)也是事先約定的,所以不能進(jìn)行改動(dòng)。

Middleware中的依賴處理:ConfigureServices方法

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

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

示例中的代碼用于向系統(tǒng)添加Mvc模塊相關(guān)的Service類型以支撐MVC功能,該方法是一個(gè)擴(kuò)展方法,用于在集合中添加與MVC相關(guān)的多個(gè)類型。

Middleware的注冊(cè)和配置:Configure方法

Configure方法的簽名如下:

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

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

// 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 =>{ /*...*/});

示例中的UseStaticFilesUseIdentityUseMvc都是IApplicationBuilder上的擴(kuò)展方法,在擴(kuò)展方法中,都會(huì)通過(guò)調(diào)用擴(kuò)展方法app.UseMiddleware方法,最終再調(diào)用app.Use方法來(lái)注冊(cè)新的Middleware,該方法定義如下:

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

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

public delegate Task RequestDelegate(HttpContext context);

通過(guò)源碼,我們可以看出,RequestDelegate是一個(gè)委托函數(shù),其接收HttpContext類型的實(shí)例,并返回一個(gè)Task類型的異步對(duì)象。也就是說(shuō)RequestDelegate是一個(gè)可以返回自身RequestDelegate類型函數(shù)的函數(shù),整個(gè)ASP.NET也就是利用這種方式構(gòu)建了管線(Pipelien)的組成,在這里,每個(gè)middleware都鏈?zhǔn)降较乱粋€(gè)middleware上,并在整個(gè)過(guò)程中可以對(duì)HttpConext對(duì)象進(jìn)行修改或維護(hù),當(dāng)然,HttpContext中就包括了我們常操作的HttpRequestHttpResponse實(shí)例對(duì)象。

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

Middleware的定義

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

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

示例如下:

public class MiddlewareName
{
 RequestDelegate _next;

 public MiddlewareName(RequestDelegate next)
 {
 _next = next;// 接收傳入的RequestDelegate實(shí)例
 }

 public async Task Invoke(HttpContext context)
 {
 // 處理代碼,如處理context.Request中的內(nèi)容

 Console.WriteLine("Middleware開(kāi)始處理");

 await _next(context);

 Console.WriteLine("Middleware結(jié)束處理");

 // 處理代碼,如處理context.Response中的內(nèi)容
 }
}

通過(guò)該模板代碼可以看到,首先一個(gè)Middleware的構(gòu)造函數(shù)要接收一個(gè)RequestDelegate的實(shí)例,先保存在一個(gè)私有變量里,然后通過(guò)調(diào)用Invoke方法(并接收HttpContent實(shí)例)并返回一個(gè)Task,并且在調(diào)用Invoke的方法中,要通過(guò)await _next(context);語(yǔ)句,鏈?zhǔn)降较乱粋€(gè)Middleware上,我們的處理代碼主要就是在鏈?zhǔn)秸Z(yǔ)句的前后執(zhí)行相關(guān)的代碼。

舉個(gè)例子,如果我們要想記錄頁(yè)面的執(zhí)行時(shí)間,首先,我們先定義一個(gè)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"">頁(yè)面處理時(shí)間:{0} 毫秒</div></body>";
 var text = string.Format(newDiv, sw.ElapsedMilliseconds);
 await context.Response.WriteAsync(text);
 }
}

Middleware的注冊(cè)有很多種方式,如下是實(shí)例型注冊(cè)代碼:

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

或者,你也可以使用UseMiddleware擴(kuò)展方法進(jìn)行注冊(cè),示例如下:

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

當(dāng)然,你也可以定義一個(gè)自己的擴(kuò)展方法用于注冊(cè)該Middleware,代碼如下:

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

最后在Startup類的Configure方法內(nèi)進(jìn)行注冊(cè),代碼如下:

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

 // 等等
}

編譯,重啟,并訪問(wèn)頁(yè)面,在頁(yè)面的底部即可看到頁(yè)面的運(yùn)行時(shí)間提示內(nèi)容。

常用Middleware功能的使用

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

app.UseErrorHandler("/Home/Error")
捕獲所有的程序異常錯(cuò)誤,并將請(qǐng)求跳轉(zhuǎn)至指定的頁(yè)面,以達(dá)到友好提示的目的。

app.UseStaticFiles()
開(kāi)啟靜態(tài)文件也能走該P(yáng)ipeline管線處理流程的功能。

app.UseIdentity()
開(kāi)啟以cookie為基礎(chǔ)的ASP.NET identity認(rèn)證功能,以支持Pipeline請(qǐng)求處理。

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

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

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
 app.Use(new Func<RequestDelegate, RequestDelegate>(next => content => Invoke(next, content)));
 // 其它
}

// 注意Invoke方法的參數(shù)
private async Task Invoke(RequestDelegate next, HttpContext content)
{
 Console.WriteLine("初始化組件開(kāi)始");
 await next.Invoke(content);
 Console.WriteLine("管道下步執(zhí)行完畢");
}

做個(gè)簡(jiǎn)便的Middleware基類

雖然有約定方法,但有時(shí)候我們?cè)陂_(kāi)發(fā)的時(shí)候往往會(huì)犯迷糊,想不起來(lái)到底是什么樣的約定,所以,在這里我們可以定義一個(gè)抽象基類,然后以后所有的Middleware在定義的時(shí)候都繼承該抽象類并重載Invoke方法即可,從而可以避免約定忘記的問(wèn)題。代碼如下:

/// <summary>
/// 抽象基類
/// </summary>
public abstract class AbstractMiddleware
{
 protected RequestDelegate Next { get; set; }
 protected AbstractMiddleware(RequestDelegate next)
 {
 this.Next = next;
 }
 public abstract Task Invoke(HttpContext context);
}

/// <summary>
/// 示例Middleware
/// </summary>
public class DemoMiddleware : AbstractMiddleware
{
 public DemoMiddleware(RequestDelegate next) : base(next)
 {
 }
 public async override Task Invoke(HttpContext context)
 {
 Console.WriteLine("DemoMiddleware Start.");
 await Next.Invoke(context);
 Console.WriteLine("DemoMiddleware End.");
 }
}

使用方法和上面的一樣。

終止鏈?zhǔn)秸{(diào)用或阻止所有的Middleware

在有些情況下,當(dāng)然根據(jù)某些條件判斷以后,可能不在需要繼續(xù)往下執(zhí)行下去了,而是想知己誒返回結(jié)果,那么你可以在你的Middleware里忽略對(duì)await next.Invoke(content);的調(diào)用,直接使用·Response.WriteAsync·方法輸出內(nèi)容。

另外,在有些情況下,你可能需要實(shí)現(xiàn)類似之前版本中的handler的功能,即不經(jīng)常任何Pipeline直接對(duì)Response進(jìn)行響應(yīng),新版ASP.NET里提供了一個(gè)run方法用于實(shí)現(xiàn)該功能,只需要在Configure方法里調(diào)用如下代碼即可實(shí)現(xiàn)類似的內(nèi)容輸出。

app.Run(async context =>
{
 context.Response.ContentType = "text/html";
 await context.Response.WriteAsync("Hello World!");
});

關(guān)于ASP.NET 5 Runtime的內(nèi)容,請(qǐng)?jiān)L問(wèn):https://msdn.microsoft.com/en-us/magazine/dn913182.aspx

遺留問(wèn)題

在Mvc項(xiàng)目中,所有的依賴注入類型都是通過(guò)IServiceProvider實(shí)例來(lái)獲取的,目前可以通過(guò)以下形式獲取該實(shí)例:

var services = Context.RequestServices; // Controller中
var services = app.ApplicationServices; // Startup中

獲取了該實(shí)例以后,即可通過(guò)如下方法來(lái)獲取某個(gè)類型的對(duì)象:

var controller = (AccountController)services.GetService(typeof(AccountController));
// 要判斷獲取到的對(duì)象是否為null

如果你引用了Microsoft.Framework.DependencyInjection命名空間的話,還可以使用如下三種擴(kuò)展方法:

var controller2 = (AccountController)services.GetService<AccountController>(); 
// 要判斷獲取到的對(duì)象是否為null

//如下兩種方式,如果獲取到的AccountController實(shí)例為null的話,就會(huì)字段拋異常,而不是返回null
var controller3 = (AccountController)services.GetRequiredService(typeof(AccountController));
var controller4 = (AccountController)services.GetRequiredService<AccountController>();

那么問(wèn)題來(lái)了?如何不在Startup和Controller里就可以獲取到HttpContext和IApplicationBuilder實(shí)例以便使用這些依賴注入服務(wù)?

如何獲取IApplicationBuilder實(shí)例?
答案:在Startup里將IApplicationBuilder實(shí)例保存在一個(gè)單例中的變量上,后期全站就可以使用了。

如何獲取HttpContext實(shí)例?
答案:參考依賴注入章節(jié)的普通類的依賴注入

引用:http://www.mikesdotnetting.com/article/269/asp-net-5-middleware-or-where-has-my-httpmodule-gone

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

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

解讀ASP.NET 5 & MVC6系列教程(6):Middleware詳解:在第1章項(xiàng)目結(jié)構(gòu)分析中,我們提到Startup.cs作為整個(gè)程序的入口點(diǎn),等同于傳統(tǒng)的Global.asax文件,即:用于初始化系統(tǒng)級(jí)的信息(例如,MVC中的路由配置)。本章我們就來(lái)一一分析,在這里如何初始化這些系統(tǒng)級(jí)的信息。 新舊版本之間的Pipeline區(qū)別 A
推薦度:
標(biāo)簽: 系列 &amp; ):
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 国产视频网 | 国产欧美在线观看一区二区 | 亚洲欧洲中文字幕 | 久久国产免费一区 | 久久久青青久久国产精品 | 日韩欧美一区二区三区视频 | 亚州色图欧美色图 | 伊人97 | 性欧美大战久久久久久久野外 | 干比网 | 国产免费资源高清小视频在线观看 | 国产一区二区三区日韩欧美 | 日韩国产欧美视频 | 中文字幕第一区 | 欧美精品一区二区在线观看 | 久久精品一级 | 国产精品毛片va一区二区三区 | 大陆一级毛片 | 国产欧美日韩一区二区三区 | 亚洲一区二区三区精品视频 | 伊人蕉| 亚洲国产精品免费 | 一级不卡毛片免费 | 在线精品欧美日韩 | 欧美日韩中文 | 久久婷婷色一区二区三区 | 国产精品亚洲一区二区在线观看 | 久久无码精品一区二区三区 | 国产成人综合欧美精品久久 | 欧美日本中文字幕 | 久久久久久久99久久久毒国产 | 亚洲国产欧美国产综合一区 | 日韩综合 | 全部费免一级毛片不收费 | 亚洲国产日韩在线一区 | 免费国产在线观看 | 亚洲国产日韩欧美在线as乱码 | 国产精品久久久久久久9999 | 亚洲欧美色图 | 欧美日韩在线亚洲国产人 | 全免费a级毛片免费毛视频 热re91久久精品国产91热 |