隨著技術(shù)的發(fā)展,ASP.NET Core MVC也推出了好長時(shí)間,經(jīng)過不斷的版本更新迭代,已經(jīng)越來越完善,本系列文章主要講解ASP.NET Core MVC開發(fā)B/S系統(tǒng)過程中所涉及到的相關(guān)內(nèi)容,適用于初學(xué)者,在校畢業(yè)生,或其他想從事ASP.NET Core MVC 系統(tǒng)開發(fā)的人員。
經(jīng)過前幾篇文章的講解,初步了解ASP.NET Core MVC項(xiàng)目創(chuàng)建,啟動(dòng)運(yùn)行,以及命名約定,創(chuàng)建控制器,視圖,模型,接收參數(shù),傳遞數(shù)據(jù)ViewData,ViewBag,路由,頁面布局,wwwroot和客戶端庫,Razor語法,EnityFrameworkCore與數(shù)據(jù)庫,HttpContext,Request,Response,Session,序列化,文件上傳,自動(dòng)映射,Html輔助標(biāo)簽,模型校驗(yàn),鑒權(quán)、授權(quán)基礎(chǔ),Identity入門,日志管理等內(nèi)容,今天繼續(xù)講解ASP.NET Core MVC 中Filter(篩選器)等相關(guān)內(nèi)容,僅供學(xué)習(xí)分享使用。
(資料圖)
什么是Filter?
Filter又稱為篩選器,過濾器。在ASP.NET Core MVC項(xiàng)目中,通過使用Filter,可以在請(qǐng)求處理管道的特定位置之前或之后運(yùn)行代碼??梢詣?chuàng)建自定義Filter,用于處理橫切關(guān)注點(diǎn),類似于AOP面向切面編程。對(duì)于創(chuàng)建Filter,可以減少代碼的復(fù)制,例如,錯(cuò)誤處理異常篩選器可以合并錯(cuò)誤處理。
Filter工作原理
從請(qǐng)求開始,到請(qǐng)求結(jié)束,經(jīng)過一系列的節(jié)點(diǎn),組成了調(diào)用管道。Filter在ASP.NET Core MVC的調(diào)用管道內(nèi)運(yùn)行,過濾器相當(dāng)于在管道中設(shè)置的幾個(gè)鉤子,用于執(zhí)行特定的代碼。
Filter類型
根據(jù)不同的處理功能,篩選器主要分為以下幾類:
授權(quán)篩選器AuthorizationFilter:
- 首先運(yùn)行。
- 確定用戶是否獲得請(qǐng)求授權(quán)。
- 如果請(qǐng)求未獲授權(quán),可以讓管道短路。
資源篩選器Resource Filter:
- 授權(quán)后運(yùn)行。
- OnResourceExecuting在篩選器管道的其余階段之前運(yùn)行代碼。 例如,
OnResourceExecuting在模型綁定之前運(yùn)行代碼。 - OnResourceExecuted在管道的其余階段完成之后運(yùn)行代碼。
操作篩選器Action Filter:
- 在調(diào)用操作方法之前和之后立即運(yùn)行。
- 可以更改傳遞到操作中的參數(shù)。
- 可以更改從操作返回的結(jié)果。
- 不可在 Razor Pages 中使用。
異常篩選器Exception Filter:在向響應(yīng)正文寫入任何內(nèi)容之前,對(duì)未經(jīng)處理的異常應(yīng)用全局策略。
結(jié)果篩選器Result Filter:
- 在執(zhí)行操作結(jié)果之前和之后立即運(yùn)行。
- 僅當(dāng)操作方法成功執(zhí)行時(shí)才會(huì)運(yùn)行。
- 對(duì)于必須圍繞視圖或格式化程序的執(zhí)行的邏輯,會(huì)很有用。
下圖展示了Filter篩選器類型在篩選器管道中的交互方式:
Filter實(shí)現(xiàn)
所有的Filter都實(shí)現(xiàn)接口IFilterMetadata,根據(jù)不同的業(yè)務(wù)類型,派生出了五個(gè)接口,分別對(duì)應(yīng)五大類Filter,如下所示:
注意:上述五個(gè)接口還有對(duì)應(yīng)異步接口(Async)。
Filter作用域
Filter可以作用在Controller,Action,全局。下面的示例闡釋了為同步操作篩選器運(yùn)行篩選器方法的順序:
授權(quán)Filter
授權(quán)篩選器:
- 是篩選器管道中運(yùn)行的第一個(gè)篩選器。
- 控制對(duì)操作方法的訪問。
- 具有在它之前的執(zhí)行的方法,但沒有之后執(zhí)行的方法。
如常用的RequireHttps就是授權(quán)篩選器,它實(shí)現(xiàn)了IAuthorizationFilter接口,并繼承了Attirbute,所以可以作用于Controller或Action中。以限制請(qǐng)求的方式。
1 using Microsoft.AspNetCore.Mvc.Filters; 2 using System; 3 4 namespace Microsoft.AspNetCore.Mvc 5 { 6 // 7 // 摘要: 8 // An authorization filter that confirms requests are received over HTTPS. 9 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]10 public class RequireHttpsAttribute : Attribute, IAuthorizationFilter, IFilterMetadata, IOrderedFilter11 {12 public RequireHttpsAttribute();13 14 //15 // 摘要:16 // Specifies whether a permanent redirect, 301 Moved Permanently, should be used17 // instead of a temporary redirect, 302 Found.18 public bool Permanent { get; set; }19 //20 // 值:21 // Default is int.MinValue + 50 to run this Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter22 // early.23 public int Order { get; set; }24 25 //26 // 摘要:27 // Called early in the filter pipeline to confirm request is authorized. Confirms28 // requests are received over HTTPS. Takes no action for HTTPS requests. Otherwise29 // if it was a GET request, sets Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext.Result30 // to a result which will redirect the client to the HTTPS version of the request31 // URI. Otherwise, sets Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext.Result32 // to a result which will set the status code to 403 (Forbidden).33 public virtual void OnAuthorization(AuthorizationFilterContext filterContext);34 //35 // 摘要:36 // Called from Microsoft.AspNetCore.Mvc.RequireHttpsAttribute.OnAuthorization(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)37 // if the request is not received over HTTPS. Expectation is Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext.Result38 // will not be null after this method returns.39 //40 // 參數(shù):41 // filterContext:42 // The Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext to update.43 //44 // 言論:45 // If it was a GET request, default implementation sets Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext.Result46 // to a result which will redirect the client to the HTTPS version of the request47 // URI. Otherwise, default implementation sets Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext.Result48 // to a result which will set the status code to 403 (Forbidden).49 protected virtual void HandleNonHttpsRequest(AuthorizationFilterContext filterContext);50 }51 }資源Filter
資源Filter在授權(quán)Filter之后執(zhí)行,需要實(shí)現(xiàn)IResourceFilter接口。如下所示:
1 using Microsoft.AspNetCore.Mvc.Filters; 2 3 namespace DemoCoreMVC.Filter 4 { 5 /// 6 /// 同步版本 7 /// 8 public class LogResourceFilter :Attribute, IResourceFilter 9 {10 public void OnResourceExecuted(ResourceExecutedContext context)11 {12 //Action執(zhí)行完成后執(zhí)行13 Console.WriteLine("********************On Resource Filter Executed********************");14 }15 16 public void OnResourceExecuting(ResourceExecutingContext context)17 {18 //授權(quán)Filter執(zhí)行后執(zhí)行。19 Console.WriteLine("********************On Resource Filter Executing********************");20 }21 }22 23 /// 24 /// 異步版本25 /// 26 public class AsynLogResouceFilter : Attribute, IAsyncResourceFilter27 {28 public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)29 {30 Console.WriteLine("********************On Aysnc Resource Filter Executing********************");31 var exceutedContext = await next();32 Console.WriteLine("********************On Async Resource Filter Executed********************");33 }34 }35 }如果要使大部分管道短路,資源篩選器會(huì)很有用。 例如,如果緩存命中,則緩存篩選器可以繞開管道的其余階段。
操作Filter
操作篩選器不應(yīng)用于 Razor Pages。 Razor Pages 支持IPageFilter和IAsyncPageFilter。
操作篩選器:
- 實(shí)現(xiàn)IActionFilter或IAsyncActionFilter接口。
- 它們的執(zhí)行圍繞著操作方法的執(zhí)行。
以下代碼顯示示例操作篩選器:
1 using Microsoft.AspNetCore.Mvc.Filters; 2 3 namespace DemoCoreMVC.Filter 4 { 5 public class DoDoActionFilter : Attribute, IActionFilter 6 { 7 public void OnActionExecuted(ActionExecutedContext context) 8 { 9 10 Console.WriteLine("********************On Action Executed********************");11 }12 13 public void OnActionExecuting(ActionExecutingContext context)14 {15 Console.WriteLine("********************On Action Executing********************");16 }17 }18 19 public class AsyncDoDoActionFilter : IAsyncActionFilter20 {21 public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)22 {23 24 Console.WriteLine("********************On Async Action Executing********************");25 await next();26 Console.WriteLine("********************On Async Action Executed********************");27 }28 }29 }ActionExecutingContext提供以下屬性:
- ActionArguments- 用于讀取操作方法的輸入。
- Controller- 用于處理控制器實(shí)例。
- Result- 設(shè)置
Result會(huì)使操作方法和后續(xù)操作篩選器的執(zhí)行短路。
ActionExecutedContext提供Controller和Result以及以下屬性:
- Canceled- 如果操作執(zhí)行已被另一個(gè)篩選器設(shè)置短路,則為 true。
- Exception- 如果操作或之前運(yùn)行的操作篩選器引發(fā)了異常,則為非 NULL 值。 將此屬性設(shè)置為 null:
- 有效地處理異常。
- 執(zhí)行
Result,從操作方法中將它返回。
對(duì)于IAsyncActionFilter,一個(gè)向ActionExecutionDelegate的調(diào)用可以達(dá)到以下目的:
- 執(zhí)行所有后續(xù)操作篩選器和操作方法。
- 返回
ActionExecutedContext。
異常Filter
異常篩選器:
- 實(shí)現(xiàn)IExceptionFilter或IAsyncExceptionFilter。
- 可用于實(shí)現(xiàn)常見的錯(cuò)誤處理策略。
下面的異常篩選器示例顯示在開發(fā)應(yīng)用時(shí)發(fā)生的異常的相關(guān)詳細(xì)信息:
1 using Microsoft.AspNetCore.Mvc.Filters; 2 3 namespace DemoCoreMVC.Filter 4 { 5 public class DoExceptionFilter :Attribute, IExceptionFilter 6 { 7 public void OnException(ExceptionContext context) 8 { 9 Console.WriteLine("********************On Exception********************");10 }11 }12 13 public class DoAsyncExceptionFilter : Attribute, IAsyncExceptionFilter14 {15 public async Task OnExceptionAsync(ExceptionContext context)16 {17 await Task.Run(() =>18 {19 Console.WriteLine("********************On Exception Async********************");20 });21 22 }23 }24 }異常篩選器:
- 沒有之前和之后的事件。
- 實(shí)現(xiàn)OnException或OnExceptionAsync。
- 處理 Razor 頁面或控制器創(chuàng)建、模型綁定、操作篩選器或操作方法中發(fā)生的未經(jīng)處理的異常。
- 請(qǐng)不要捕獲資源篩選器、結(jié)果篩選器或 MVC 結(jié)果執(zhí)行中發(fā)生的異常。
若要處理異常,請(qǐng)將ExceptionHandled屬性設(shè)置為true或分配Result屬性。 這將停止傳播異常。 異常篩選器無法將異常轉(zhuǎn)變?yōu)椤俺晒Α薄?只有操作篩選器才能執(zhí)行該轉(zhuǎn)變。
異常篩選器:
- 非常適合捕獲發(fā)生在操作中的異常。
- 并不像錯(cuò)誤處理中間件那么靈活。
建議使用中間件處理異常。 基于所調(diào)用的操作方法,僅當(dāng)錯(cuò)誤處理不同時(shí),才使用異常篩選器。 例如,應(yīng)用可能具有用于 API 終結(jié)點(diǎn)和視圖/HTML 的操作方法。 API 終結(jié)點(diǎn)可以將錯(cuò)誤信息返回為 JSON,而基于視圖的操作可能會(huì)以 HTML 形式返回錯(cuò)誤頁。
結(jié)果Filter
結(jié)果篩選器:
- 實(shí)現(xiàn)接口:
- IResultFilter或IAsyncResultFilter
- IAlwaysRunResultFilter或IAsyncAlwaysRunResultFilter
- 它們的執(zhí)行圍繞著操作結(jié)果的執(zhí)行。
1 using Microsoft.AspNetCore.Mvc.Filters; 2 3 namespace DemoCoreMVC.Filter 4 { 5 public class DoResultFilter :Attribute, IResultFilter 6 { 7 public void OnResultExecuted(ResultExecutedContext context) 8 { 9 Console.WriteLine("********************On Result Executed********************");10 }11 12 public void OnResultExecuting(ResultExecutingContext context)13 {14 Console.WriteLine("********************On Result Executing********************");15 }16 }17 18 public class DoAysncResultFilter :Attribute, IAsyncResultFilter19 {20 public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)21 {22 Console.WriteLine("********************On Result Execution Async Executing********************");23 await next();24 Console.WriteLine("********************On Result Execution Async Executed********************");25 }26 }27 28 }Filter測試
將寫好的過濾器,放在Home/Index上,如下所示:
1 [DoExceptionFilter]2 [LogResourceFilter]3 [DoResultFilter]4 [DoDoActionFilter]5 public IActionResult Index()6 {7 _logger.LogInformation("Hello, 這是首頁!");8 return View();9 }測試如下所示:
說明:異常過濾器沒有輸出內(nèi)容,是因?yàn)闆]有異常產(chǎn)生。授權(quán)過濾器沒有添加,在所有過濾器之前開始,所有過濾器之后結(jié)束。
Filter全局應(yīng)用
Filter可以應(yīng)用在單個(gè)Controller或Action上,也可以進(jìn)行全局應(yīng)用,代碼如下所示:
1 builder.Services.AddControllersWithViews(option =>2 {3 option.Filters.Add();4 option.Filters.Add();5 option.Filters.Add();6 option.Filters.Add();7 }); 全局測試如下所示:
以上就是ASP.NET Core MVC 從入門到精通之Filter的全部內(nèi)容。
參考文檔
官方文檔:https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0
營業(yè)執(zhí)照公示信息