一、前言
在分享ASP.NET Core Filter 使用之前,先來談談AOP,什么是AOP 呢?
AOP全稱Aspect Oriented Programming意為面向切面編程,也叫做面向方法編程,是通過預編譯方式和運行期動態代理的方式實作不修改源代碼的情況下給程式動態統一添加功能的技術,
AOP技術利用一種稱為“橫切”的技術,剖解開封裝物件的內部,將影響多個類的公共行為封裝到一個可重用的模塊中,并將其命名為Aspect切面,所謂的切面,簡單來說就是與業務無關,卻為業務模塊所共同呼叫的邏輯,將其封裝起來便于減少系統的重復代碼,降低模塊的耦合度,有利用未來的可操作性和可維護性,
利用AOP可以對業務邏輯各個部分進行隔離,從而使業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高開發效率,
AOP的使用場景主要包括日志記錄、性能統計、安全控制、事務處理、例外處理等,

二、Filter-過濾器
Filter是延續ASP.NET MVC的產物,同樣保留了五種的Filter,分別是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter,
通過不同的Filter可以有效處理封包進出的加工,本篇將介紹ASP.NET Core的五種Filter運作方式,
2.1 Filter 介紹
ASP.NET Core 有以下五種Filter 可以使用:
- Authorization Filter:
Authorization是五種Filter中優先級最高的,通常用于驗證Request合不合法,不合法后面就直接跳過, - Resource Filter:Resource是第二優先,會在Authorization之后,Model Binding之前執行,通常會是需要對Model加工處理才用,
- Exception Filter:例外處理的Filter,
- Action Filter:最常使用的Filter,封包進出都會經過它,使用上沒什么需要特別注意的,跟Resource Filter很類似,但并不會經過Model Binding,
- Result Filter:當Action完成后,最侄訓經過的Filter,

三、五大Filter 的應用
這一篇章主要來講解Asp.Net Core 的五大過濾器的實作及用途.
3.1 Authonization Filter
權限控制過濾器
通過 Authonization Filter 可以實作復雜的權限角色認證、登陸授權等操作
實作事例代碼如下:
public class AuthonizationFilter :Attribute,IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
//這里可以做復雜的權限控制操作
if (context.HttpContext.User.Identity.Name != "1") //簡單的做一個示范
{
//未通過驗證則跳轉到無權限提示頁
RedirectToActionResult content = new RedirectToActionResult("NoAuth", "Exception", null);
context.Result = content;
}
}
}
3.2 Resource Filter
資源過濾器
可以通過Resource Filter 進行資源快取、防盜鏈等操作,
使用Resource Filter 要求實作IResourceFilter 抽象介面
public class ResourceFilter : Attribute,IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
// 執行完后的操作
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
// 執行中的過濾器管道
}
}
3.3 Exception Filter
通過Execption Filter 過濾器可以進行全域的例外日志收集 等操作,
使用Execption Filter 要求實作IExceptionFilter 抽象介面
IExceptionFilter介面會要求實作OnException方法,當系統發生未捕獲例外時就會觸發這個方法,OnException方法有一個ExceptionContext例外背景關系,其中包含了具體的例外資訊,HttpContext及mvc路由資訊,系統一旦出現未捕獲例外后,比較常見的做法就是使用日志工具,將例外的詳細資訊記錄下來,方便修正除錯,下面是日志記錄的實作,
public class ExecptionFilter : Attribute, IExceptionFilter
{
private ILogger<ExecptionFilter> _logger;
//構造注入日志組件
public ExecptionFilter(ILogger<ExecptionFilter> logger)
{
_logger = logger;
}
public void OnException(ExceptionContext context)
{
//日志收集
_logger.LogError(context.Exception, context?.Exception?.Message??"例外");
}
}
3.4 Action Filter
作用:可以通過ActionFilter 攔截 每個執行的方法進行一系列的操作,比如:執行操作日志、引數驗證,權限控制 等一系列操作,
使用Action Filter 需要實作IActionFilter 抽象介面,IActionFilter 介面要求實作OnActionExecuted 和OnActionExecuting 方法
public class ActionFilter : Attribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
//執行完成....
}
public void OnActionExecuting(ActionExecutingContext context)
{
//執行中...
}
}
3.5 Result Filter
結果過濾器,可以對結果進行格式化、大小寫轉換等一系列操作,
使用Result Filter 需要實作IResultFilter 抽象介面,介面要求實作
OnResultExecuting 方法 和OnResultExecuted 方法
OnResultExecuting:Called before the action result executes. 在操作結果執行之前呼叫OnResultExecuted:Called after the action result executes. 在操作結果執行之后呼叫
具體代碼實作代碼如下:
public class ResultFilter : Attribute, IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
// 在結果執行之后呼叫的操作...
}
public void OnResultExecuting(ResultExecutingContext context)
{
// 在結果執行之前呼叫的一系列操作
}
}
四、Asp.Net Core 過濾器的注冊方式
這一篇章主要來分析探討Asp.Net Core 中過濾器的三種注冊方式Action、Controller、全域 ,
4.1 Action 注冊方式
Action 注冊方式是區域注冊方式,針對控制器中的某個方法上標注特性的方式進行注冊,代碼如下:
[AuthonizationFilter()]
public IActionResult Index()
{
return View();
}
4.2 Controller 注冊方式
了解過Action 特性注冊方式的同學,一定發現了它的不好之處就是我一個控制器里面需要使用同一套Filter 的時候,需要一個一個Action 標注特性注冊,是不是很繁瑣呢?有沒有其他方式進行代替這些繁瑣的操作呢?微軟給我們提供了簡便的控制器標注注冊方式,代碼如下:
[AuthonizationFilter()]
public class FirstController : Controller
{
private ILogger<FirstController> _logger;
public FirstController(ILogger<FirstController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
}
4.3 全域注冊方式
現在有些同學考慮了一些全域的情況,比如我要全域處理系統中的例外,或者收集操作日志等,需要全域注冊一個ExceptionFilter 來實作,就不需要每一個Controller 中進行代碼注冊,方便快捷,代碼如下:
public void ConfigureServices(IServiceCollection services)
{
//全域注冊例外過濾器
services.AddControllersWithViews(option=> {
option.Filters.Add<ExecptionFilter>();
});
services.AddSingleton<ISingletonService, SingletonService>();
}
4.4 TypeFilter 和 ServiceFilter 注冊方式
上面的五大過濾器中事例代碼中其中有一個過濾器的代碼比較特,再來回顧ExceptionFilter過濾器的實作代碼:
public class ExecptionFilter : Attribute, IExceptionFilter
{
private ILogger<ExecptionFilter> _logger;
//構造注入日志組件
public ExecptionFilter(ILogger<ExecptionFilter> logger)
{
_logger = logger;
}
public void OnException(ExceptionContext context)
{
//日志收集
_logger.LogError(context.Exception, context?.Exception?.Message??"例外");
}
}
從上面的代碼中可以發現 ExceptionFilter 過濾器實作中存在日志服務的建構式的注入,也就是說該過濾器依賴于其他的日志服務,但是日志服務都是通過DI 注入進來的;再來回顧下上面Action 注冊方式或者Controller 注冊方式 也即Attribute 特性標注注冊方式,本身基礎的特性是不支持建構式的,是在運行時注冊進來的,那要解決這種本身需要對服務依賴的過濾器需要使用 TypeFilter 或者ServiceFilter 方式進行過濾器的標注注冊,
TypeFilter 和ServiceFilter 的區別,
- ServiceFilter和TypeFilter都實作了IFilterFactory
- ServiceFilter需要對自定義的Filter進行注冊,TypeFilter不需要
- ServiceFilter的Filter生命周期源自于您如何注冊,而TypeFilter每次都會創建一個新的實體
TypeFilter 使用方式
代碼如下:
[TypeFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
return View();
}
通過上面的代碼可以發現AuthonizationFilter 是默認的構造器,但是如果過濾器中建構式中存在引數,需要注入服務那該怎么辦呢?,比如上面的ExceptionFilter 代碼,就不能使用這種方式進行注冊,需要使用服務特性的方式,我們可以選擇使用 代碼如下:
[TypeFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
return View();
}
ServiceFilter 使用方式
控制器中的代碼如下:
[ServiceFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
return View();
}
注冊服務的代碼如下:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
Console.WriteLine("ConfigureServices");
services.AddControllersWithViews();
//services.AddControllersWithViews(option=> {
// option.Filters.Add<ExecptionFilter>();
//});
//注冊過濾器服務,使用ServiceFilter 方式必須要注冊 否則會報沒有注冊該服務的相關例外
services.AddSingleton<ExecptionFilter>();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/59647.html
標籤:.NET Core
