您好,登錄后才能下訂單哦!
ASP.NET中Middleware的作用是什么,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
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 =>{ /*...*/});
示例中的UseStaticFiles、UseIdentity、UseMvc都是IApplicationBuilder上的擴展方法,在擴展方法中,都會通過調用擴展方法app.UseMiddleware方法,最終再調用app.Use方法來注冊新的Middleware,該方法定義如下:
public interface IApplicationBuilder { //... IApplicationBuilder Use(Func
通過代碼,可以看出,middleware是Func
public delegate Task RequestDelegate(HttpContext context);
通過源碼,我們可以看出,RequestDelegate是一個委托函數,其接收HttpContext類型的實例,并返回一個Task類型的異步對象。也就是說RequestDelegate是一個可以返回自身RequestDelegate類型函數的函數,整個ASP.NET也就是利用這種方式構建了管線(Pipelien)的組成,在這里,每個middleware都鏈式到下一個middleware上,并在整個過程中可以對HttpConext對象進行修改或維護,當然,HttpContext中就包括了我們常操作的HttpRequest和HttpResponse實例對象。
注意:HttpContext、HttpRequest、HttpResponse在ASP.NET 5中都是重新定義的新類型。
Middleware的定義
既然每個middleare都是Func
構造函數的***個參數必須是處理管線中的下一個處理函數,即RequestDelegate;
必須有一個 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 = @"
頁面處理時間:{0} 毫秒
";
var text = string.Format(newDiv, sw.ElapsedMilliseconds);
await context.Response.WriteAsync(text);
}
}
Middleware的注冊有很多種方式,如下是實例型注冊代碼:
app.Use(next => new TimeRecorderMiddleware(next).Invoke);
或者,你也可以使用UseMiddleware擴展方法進行注冊,示例如下:
app.UseMiddleware(); //app.UseMiddleware(typeof(TimeRecorderMiddleware)); 兩種方式都可以
當然,你也可以定義一個自己的擴展方法用于注冊該Middleware,代碼如下:
public static IApplicationBuilder UseTimeRecorderMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware(); }
***在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
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory) { app.Use(new Func
做個簡便的Middleware基類
雖然有約定方法,但有時候我們在開發的時候往往會犯迷糊,想不起來到底是什么樣的約定,所以,在這里我們可以定義一個抽象基類,然后以后所有的Middleware在定義的時候都繼承該抽象類并重載Invoke方法即可,從而可以避免約定忘記的問題。代碼如下:
/// /// 抽象基類 /// public abstract class AbstractMiddleware { protected RequestDelegate Next { get; set; } protected AbstractMiddleware(RequestDelegate next) { this.Next = next; } public abstract Task Invoke(HttpContext context); } /// /// 示例Middleware /// 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."); } }
使用方法和上面的一樣。
終止鏈式調用或阻止所有的Middleware
在有些情況下,當然根據某些條件判斷以后,可能不在需要繼續往下執行下去了,而是想知己誒返回結果,那么你可以在你的Middleware里忽略對await next.Invoke(content);的調用,直接使用·Response.WriteAsync·方法輸出內容。
另外,在有些情況下,你可能需要實現類似之前版本中的handler的功能,即不經常任何Pipeline直接對Response進行響應,新版ASP.NET里提供了一個run方法用于實現該功能,只需要在Configure方法里調用如下代碼即可實現類似的內容輸出
app.Run(async context => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync("Hello World!"); });
關于ASP.NET 5 Runtime的內容,請訪問:https://msdn.microsoft.com/en-us/magazine/dn913182.aspx
遺留問題
在Mvc項目中,所有的依賴注入類型都是通過IServiceProvider實例來獲取的,目前可以通過以下形式獲取該實例:
var services = Context.RequestServices; // Controller中 var services = app.ApplicationServices; // Startup中
獲取了該實例以后,即可通過如下方法來獲取某個類型的對象:
var controller = (AccountController)services.GetService(typeof(AccountController)); // 要判斷獲取到的對象是否為null
如果你引用了Microsoft.Framework.DependencyInjection命名空間的話,還可以使用如下三種擴展方法:
var controller2 = (AccountController)services.GetService(); // 要判斷獲取到的對象是否為null //如下兩種方式,如果獲取到的AccountController實例為null的話,就會字段拋異常,而不是返回null var controller3 = (AccountController)services.GetRequiredService(typeof(AccountController)); var controller4 = (AccountController)services.GetRequiredService();
看完上述內容,你們掌握ASP.NET中Middleware的作用是什么的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。