Filter總共有五種,Authorization Filter,Resource Filter,Exception Filter,Action Filter,Result Filter
Exception Filter 設置 新增全局異常過濾器GlobalExceptionFilter.cs, 當出現異常時進入此方法,可在這針對不同的異常做相關處理並返回指定數據,避免直接把錯誤暴露給用戶
public class GlobalExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { Exception ex = context.Exception; string errMsg = "GlobalExceptionFilter-OnException:" + ex.Message; if (context.Exception.GetType() == typeof(ExecuteException)) { //針對不同的自定義異常,做不同處理 MsgModel<string> msgModel = new MsgModel<string>() { Status = false, Msg = errMsg, Errcode = "AA001" }; context.Result = new JsonResult(msgModel); context.ExceptionHandled = true; } else { context.Result = new JsonResult(errMsg); context.ExceptionHandled = true; } LogHelper.Error(errMsg); } }
然后在Startup.cs 注入過濾器
Action Filter 設置
新增全局過濾器GlobalActionFilter.cs
在方法執行前后,會跳轉至以下兩個方法,方便追蹤接口執行情況
public class GlobalActionFilter : IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { //LogHelper.Info("OnActionExecuted"); //執行方法后執行這 } public void OnActionExecuting(ActionExecutingContext context) { //LogHelper.Info("OnActionExecuting"); //執行方法前先執行這 } }
Authonization Filter
權限控制過濾器
通過 Authonization Filter 可以實現復雜的權限角色認證
、登陸授權
等操作
/// <summary> /// 實現自定義授權 /// </summary> public class AuthorizeFilter : IAuthorizationFilter { /// <summary> /// 請求驗證,當前驗證部分不要拋出異常,ExceptionFilter不會處理 /// </summary> /// <param name="context"></param> public void OnAuthorization(AuthorizationFilterContext context) {
//這里可以做復雜的權限控制操作
//if (context.HttpContext.User.Identity.Name != "1") //簡單的做一個示范
//{
// //未通過驗證則跳轉到無權限提示頁
// RedirectToActionResult content = new RedirectToActionResult("NoAuth", "Exception", null);
// context.Result = content;
//
} }
Resource Filter
資源過濾器
可以通過Resource Filter 進行資源緩存
、防盜鏈
等操作。
使用Resource Filter 要求實現IResourceFilter 抽象接口
public class ResourceFilter : Attribute,IResourceFilter { public void OnResourceExecuted(ResourceExecutedContext context) { // 執行完后的操作 } public void OnResourceExecuting(ResourceExecutingContext context) { // 執行中的過濾器管道 } }
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) { // 在結果執行之前調用的一系列操作 } }
完畢 可以在全局注入
AOP攔截器
其實好多項目中,做一些數據攔截、數據緩存都有Aop的概念,只是實現方式不一樣;之前大家可能都會利用過濾器來實現Aop的功能,如果是Asp.NetCore的話,也可能會使用中間件; 而這種實現方式都是在請求過程中進行攔截,如果我們想在服務層中做切面的話,那種方式顯然不好使了,需要用到“真正的Aop”。
真正的Aop”其實就是動態代理
LogInterceptor 設置
安裝Castle.Core,Autofac.Extras.DynamicProxy
新建LogInterceptor.cs ,繼承IInterceptor
public class LogInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { try { invocation.Proceed(); Dapper.Logger.LogHelper.logger.Info(invocation.Method.Name); } catch (Exception ex) { Dapper.Logger.LogHelper.logger.Error(invocation.Method.Name + " " + ex.ToString()); } } }
在Startup.cs 新增以下代碼
針對某個類或者某個方法做攔截時
首先新建一個攔截器 MyInterceptor
public class MyInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { try { invocation.Proceed(); NLogHelper.logger.Info(invocation.Method.Name); } catch (Exception ex) { NLogHelper.logger.Error(invocation.Method.Name + " " + ex.ToString()); } } }
然后Startup.cs 中ConfigureContainer代碼如下
把LogInterceptor 代碼注釋,但是要保留接口攔截EnableInterfaceInterceptors() ,注入MyInterceptor
public void ConfigureContainer(ContainerBuilder builder) { //builder.RegisterType<LogInterceptor>(); builder.RegisterType<MyInterceptor>(); builder.RegisterType<DbFactory>().As<IDbFactory>(); //業務邏輯層所在程序集命名空間 Assembly service = Assembly.Load("Summer.Service"); //注:webapi要引用接口和類,不然這里讀不到 //接口層所在程序集命名空間 Assembly repository = Assembly.Load("Summer.IService"); //自動注入 builder.RegisterAssemblyTypes(service, repository) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces() .InstancePerLifetimeScope() .EnableInterfaceInterceptors() //開啟接口攔截 //.InterceptedBy(typeof(LogInterceptor)) //設置全局攔截器,統一由LogInterceptor攔截所有接口的調用 ; }
然后在需要攔截的接口中添加以下代碼
攔截器設置完畢,當調用ITestService 的全部方法都會跳轉攔截器
Filter和 LogInterceptor 可以同時共存,執行順序是:
ActionFilter 的OnActionExecuting =》LogInterceptor 的Intercept =》ActionFilter 的OnActionExecuted
如果接口有異常,不會跳轉LogInterceptor ,而是進入ExceptionFilter,順序是:
ActionFilter 的OnActionExecuting =》ActionFilter 的OnActionExecuted =》ExceptionFilter 的OnException
原文 https://www.cnblogs.com/redo/p/12575119.html
AOP的應用
引入三個包,通過Nuget安裝,Autofac開頭,如下
注: 其中Autofac.Extras.DynamicProxy就是AOP相關組件,其中包含了Castle.Core,所以不用單獨安裝Castle.Core.
總結:
AOP在做一些業務前置或后置處理上時很有用的,使用比較靈活,無需修改原有代碼邏輯,比起修改原有代碼維護相對好多啦!!!