經過一週的時間沒有分享文章了,主要是在使用.netcore做一個小的專案,專案面向大眾使用者的增刪改查都做的差不多了,打算本週在雲伺服器上部署試試,很期待,也希望上線後大家多多支援;以上純屬個人廢話,來一起看看今天的正篇環節:
.繼承IActionFilter來定義個驗證登入的流程例子
.ActionFilter中怎麼使用依賴注入
下面一步一個腳印的來分享:
.繼承IActionFilter來定義個驗證登入的流程例子
首先,咋們定義一個名叫FilterTestController的Controller,返回一個JsonResult結果;為了例子檢視的方便性,同時在此檔案中定義一個名MoResponse的類,對應的程式碼如下:
1 public class FilterTestController : Controller 2 { 3 public JsonResult Index() 4 { 5 var response = new MoResponse(); 6 response.Status = 1; 7 8 return Json(response); 9 } 10 } 11 12 public class MoResponse 13 { 14 15 public int Status { get; set; } 16 public string Des { get; set; } = "Ok"; 17 }
然後,執行一下執行命令dotnet run,瀏覽器中輸入預設埠好5000並訪問剛才定義的Action,地址如:http://localhost:5000/FilterTes,不出意外大家都能看到如下結果的圖樣:
這表示專案初建沒有問題;
接著,建立一個類,名稱為CheckLoginAttribute並且繼承和實現Attribute, IActionFilter,這裡實現IActionFilter介面的OnActionExecuting,OnActionExecuted兩個方法,看方法名稱字尾大概就明白一個是Action執行之前,一個是Action方法執行之後呼叫的,這裡簡單補充下以前的mvc版本大部分都是去繼承ActionFilterAttribute,其實這個也去繼承和實現了Attribute, IActionFilter,不過還有其他的擴充套件罷了,這裡不詳細區分說明:
然後咋們分別在兩個OnActionExecut中增加一些輸入資訊,並且在FilterTestController的Index方法上方增加[CheckLogin]標記,程式碼如下:
public class CheckLoginAttribute : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { Console.WriteLine(DateTime.Now + "end..."); } public void OnActionExecuting(ActionExecutingContext context) { Console.WriteLine(DateTime.Now + "start..."); //context.Result = new RedirectResult("http://www.cnblogs.com/"); } }
再執行起來,訪問剛才的路由,可以在命令窗體看到如圖:
剛才說的CheckLoginAttribute中的OnActionExecuting對應的是呼叫Controller的Action方法之前執行的部分,上面程式碼剛才註釋的部分context.Result = new RedirectResult("http://www.cnblogs.com/");是跳轉到該http://www.cnblogs.com/地址中去,如果放開註釋,看到的效果是訪問之前Controller路由後直接跳轉到了該地址,並且名利窗體中只有start...日誌的部分,沒有了之前end...的部分,可以看出這裡context.Result效果是直接終止了程式繼續往下執行;到這裡就可以走一個簡單登入的驗證了,我這裡只說下流程,不做具體程式碼,因為這不是重點哈哈:
1.在OnActionExecuting方法中使用context.HttpContext.Session獲取使用者登陸的session(當然其他session儲存方式除外)
2.使用context.HttpContext.Request.Path獲取當前訪問的路由地址
3.如果session為空,使用context.Result = new RedirectResult("/Login?returnUrl=" + context.HttpContext.Request.Path);跳轉到路由Login中去,returnUrl引數使用來傳遞登陸有再跳轉到當前訪問地址中去
.ActionFilter中怎麼使用依賴注入
這個是值得關注的地方,這個在我的專案最初寫的時候遇到的問題;下面是一些分析,可供大家參考:
1.netcore常用的注入方式是通過建構函式注入的
2.通過建構函式注入後,在需要使用Filter的Action中無法通過對應引數個數的建構函式呼叫;只能呼叫無參的Filter建構函式
3.注意在需要使用依賴注入的Filter中不用定義無參建構函式(這裡實驗過了,如果定義TypeFilter將會以無參建構函式為優先建立例項,這樣將會是依賴注入失敗)
以上就是最開始無法直接使用結構器依賴注入的原因,後面無意中發現一個很有用的過濾器:TypeFilterAttribute,該過濾器可以通過建構函式傳遞進去的物件例項化,下面我們一起來看下:
首先,我們定義個MyActionFilterAttribute類並且繼承TypeFilterAttribute,預設繼承建構函式,然後在Controller的Index上方使用這個自定義屬性並且傳遞我們定義的CheckLoginAttribute型別為引數,如下程式碼:
[MyActionFilter(typeof(CheckLoginAttribute))] public JsonResult Index() { var response = new MoResponse(); response.Status = 1; return Json(response); }
MyActionFilterAttribute程式碼如下:
public class MyActionFilterAttribute : TypeFilterAttribute { public MyActionFilterAttribute(Type type) : base(type) { } }
好了,咋們再自定義個簡單的服務,並且把定義的服務在Startup.cs檔案中增加程式碼services.AddTransient<LogService>();注入服務,服務要求是定義個方法,在命令框中輸出hello...,如下程式碼:
public class LogService { public async void _LogRequest() { await Task.Run(() => { for (int i = 0; i < 10; i++) { Console.WriteLine(DateTime.Now + "hello..."); } }); } }
再來,CheckLoginAttribute中增加程式碼如:
1 public class CheckLoginAttribute : Attribute, IActionFilter 2 { 3 private readonly LogService _logService; 4 public CheckLoginAttribute(LogService logService) 5 { 6 7 _logService = logService; 8 } 9 10 public void OnActionExecuted(ActionExecutedContext context) 11 { 12 13 Console.WriteLine(DateTime.Now + "end..."); 14 } 15 16 public void OnActionExecuting(ActionExecutingContext context) 17 { 18 19 Console.WriteLine(DateTime.Now + "start..."); 20 21 var path = context.HttpContext.Request.Path; 22 //context.Result = new RedirectResult($"/Login?returnUrl={path}"); 23 24 _logService._LogRequest(); 25 } 26 }
好了咋們一起dotnet run看到的效果如:
這個依賴注入到Filter中就成功了,其實上面定義的MyActionFilterAttribute也可以看做多餘吧,因為在Action上使用的其實就是TypeFilterAttribute自身的建構函式方法,咋們可以直接在Action上使用TypeFilter如圖:
兩者效果是一樣的,只是定義一個Filter可以記錄其他的日誌資訊或幹其他的事情罷了;這次分享的內容就是這樣了,不知道描述的是否清晰,希望多多支援,謝謝。