asp.net mvc 之旅 —— 第六站 ActionFilter的應用及源碼分析

来源:http://www.cnblogs.com/huangxincheng/archive/2016/07/14/5671106.html
-Advertisement-
Play Games

這篇文章我們開始看一下ActionFilter,從名字上其實就大概知道ActionFilter就是Action上的Filter,對吧,那麼Action上的Filter大概有幾個呢??? 這個問題其實還是蠻簡單的,因為我們聽說Mvc本身就是一個擴展性極強的框架,自然就是層層有攔截,層層有過濾,對吧,比 ...


  

     這篇文章我們開始看一下ActionFilter,從名字上其實就大概知道ActionFilter就是Action上的Filter,對吧,那麼Action上的Filter大概有幾個呢???

這個問題其實還是蠻簡單的,因為我們聽說Mvc本身就是一個擴展性極強的框架,自然就是層層有攔截,層層有過濾,對吧,比如我們看到的如下Controller類。

    public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IController, IAsyncManagerContainer
    {
    }

從這個父類的Controller中,我們就可以看到有5個Filter,如:IActionFilter,IAuthenticationFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter,

對吧,首先我們還是從第一個ActionFilter說起。

 

一:IActionFilter解析

  現在我們知道IActionFilter是一個介面,接下來感興趣的就是這個ActionFilter裡面到底是什麼,比如我下麵截圖的這樣。

    //
    // 摘要:
    //     Defines the methods that are used in an action filter.
    public interface IActionFilter
    {
        //
        // 摘要:
        //     Called after the action method executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnActionExecuted(ActionExecutedContext filterContext);
        //
        // 摘要:
        //     Called before an action method executes.
        //
        // 參數:
        //   filterContext:
        //     The filter context.
        void OnActionExecuting(ActionExecutingContext filterContext);
    }

 從上面這段代碼中,我們可以看到其實這個介面裡面只有兩個方法,一個是OnActionExecuting,一個是OnActionExecuted,看這名字你應該就明白

其實就是在Action的前後分別執行,對吧,那這樣的話,聰明的你就想到了應用場景,記錄日誌,獲取action的訪問量,以方便後續收費~~~ 接下來我

們來看看怎麼來實現這兩個方法。

 

1.  用override的方式實現ActionFilter

     現在大家都知道Controller類已經實現了這個介面,那我們自己的XXXController剛好又繼承了這個父Controller,所以面對這種情況,我們可以用

override來實現,比如下麵我實現的這樣。

 1     public class HomeController : Controller
 2     {
 3         public ActionResult Index()
 4         {
 5             return View();
 6         }
 7 
 8         protected override void OnActionExecuting(ActionExecutingContext filterContext)
 9         {
10             filterContext.HttpContext.Response.Write("hello");
11 
12             base.OnActionExecuting(filterContext);
13         }
14 
15         protected override void OnActionExecuted(ActionExecutedContext filterContext)
16         {
17             filterContext.HttpContext.Response.Write("world");
18 
19             base.OnActionExecuted(filterContext);
20         }
21     }

就這樣我們就輕鬆加愉快的實現了,是不是很簡單,但是仔細一想,這樣的方法還是有一點限制的,也就是說我們override的依賴性太強了,比如說只有

class extends IActionFilter才可以,接下來我們再看有沒有更靈活的方法來實現。

 

2.  自定義class extends IActionFilter

    要想做到高度的靈活性,我們必須將這個實現類做成一個“原子單位”,有了這個原子單位,我們就可以很方便的將這個不可拆解的原子性應用到各個地方

去,對吧,這個原子在C#中可以用Attribute來實現,比如下麵這樣:

 1     public class MyActionFilterAttribute : Attribute, IActionFilter
 2     {
 3         public void OnActionExecuted(ActionExecutedContext filterContext)
 4         {
 5             filterContext.HttpContext.Response.Write("hello");
 6         }
 7 
 8         public void OnActionExecuting(ActionExecutingContext filterContext)
 9         {
10             filterContext.HttpContext.Response.Write("world");
11         }
12     }

 

ok,現在我們已經得到了一個原子性質的MyActionFilterAttribute特性,接下來我們可以將這個MyActionFilterAttribute應用到任何地方,如下圖:

1     public class HomeController : Controller
2     {
3         [MyActionFilter]
4         public ActionResult Index()
5         {
6             return View();
7         }
8     }

 

3.  ActionFilterAttribute

     除了我們實現以下Attribute特性和IActionFilter介面,我們還可以繼承一個mvc框架提供給我們的ActionFilterAttribute特性,迫不及待的看一下吧~

 1     //
 2     // 摘要:
 3     //     Represents the base class for filter attributes.
 4     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
 5     public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
 6     {
 7         //
 8         // 摘要:
 9         //     Initializes a new instance of the System.Web.Mvc.ActionFilterAttribute class.
10         protected ActionFilterAttribute();
11 
12         //
13         // 摘要:
14         //     Called by the ASP.NET MVC framework after the action method executes.
15         //
16         // 參數:
17         //   filterContext:
18         //     The filter context.
19         public virtual void OnActionExecuted(ActionExecutedContext filterContext);
20         //
21         // 摘要:
22         //     Called by the ASP.NET MVC framework before the action method executes.
23         //
24         // 參數:
25         //   filterContext:
26         //     The filter context.
27         public virtual void OnActionExecuting(ActionExecutingContext filterContext);
28         //
29         // 摘要:
30         //     Called by the ASP.NET MVC framework after the action result executes.
31         //
32         // 參數:
33         //   filterContext:
34         //     The filter context.
35         public virtual void OnResultExecuted(ResultExecutedContext filterContext);
36         //
37         // 摘要:
38         //     Called by the ASP.NET MVC framework before the action result executes.
39         //
40         // 參數:
41         //   filterContext:
42         //     The filter context.
43         public virtual void OnResultExecuting(ResultExecutingContext filterContext);
44     }

 

從這個Attribute中可以看到,它整合了IActionFilter, IResultFilter,自然就有了這兩個介面的方法,好了,不多說,我們來實現一下這個抽象類吧。

namespace WebApplication2.Controllers
{
    public class HomeController : Controller
    {
       [MyActionFilter]
       public ActionResult Index()
        {
            return View();
        }
    }

    public class MyActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
        }
    }
}

 

二:源碼分析

     最好的源碼分析方法,肯定是希望你下載一個reflector插件,這樣我們就可以獲取到運行時的可調試代碼以及可以看到的調用堆棧,尤其是”調用堆

棧“,對你來說非常的重要。

 

1. 首先我們下一個斷點在 OnActionExecuting方法裡面,如下圖:

 

2. 通過調用堆棧回退到上一個堆棧,如圖:

 

這個方法其實非常的有意思,從方法名稱中可以看到,其實它是一個遞歸的模式,也就是”OnActionExecuting" =>"進棧執行BeginInvokeActionMethod”

=>"退棧執行OnActionExecuted“方法,因為有一個非常好看的statement,比如: 

Func<ActionExecutedContext> continuation = this.InvokeActionMethodFilterAsynchronouslyRecursive(num);

 

好了,更多的細節等待你去考究,希望本篇文章對您有幫助~~~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 預設情況下,有以下控制項已經支持UIMenuController UITextField UITextView UIWedView 以UITable為例,說明點擊後彈出複製剪切粘貼等為例 使用的整體思路:(系統自帶的文字) 1、新建一個UILabel的類,如果想以後storyboard和Xib都可以用 ...
  • 最近在做的新聞客戶端用到了ViewPager,Android Studio如今集成的很好了,自動創建很多不必要寫的代碼。 在使用過程中碰到了一個很奇怪的事:ViewPager中載入的數據重覆 具體的看圖就明白了: 可以看到載入出來的數據,1、2頁面出現了重覆,而3恢復正常 在困擾許久之後博主在sta ...
  • 我們知道在iOS開發時,控制項UITextField有個placeholder屬性,UITextField和UITextView使用方法基本類似,有兩個小區別:1.UITextField單行輸入,而UITextView可以多行輸入。2.UITextField有placeholder屬性,而UIText ...
  • cocoapods簡介: cocoapods簡介: cocoapods 是iOS的類庫管理工具,可以讓開發者很方便集成各種第三方庫,而不用去網站上一個個下載,再一個個文件夾的拖進項目中,還得添加相關的系統依賴庫。只需要安裝好cocoapods,然後編寫好Podfile,最好在終端輸入一行命令,就可以 ...
  • 在生產環境下麵對紛繁的業務處理場景,我們知道要處理很多邏輯代碼,其中有個叫枚舉(也稱窮舉),當處理這類事務時,會產生大量的迴圈執行,而迴圈是最耗CPU的,大量的迭代計算,可直接拉低計算速度,怎麼處理這類問題呢? 對於事務的不定項的選擇幾率,都會有一定的規律,比如說事件的概率發生,根據概率論的知識,我 ...
  • DMA(Direct Memory Access),直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,通過硬體為RAM與I/O設備開闢一條直接傳送數據的通路,使CPU效率大大提高。stm32f103有2個DMA控制器,DMA1有7個通道,DMA2有5個通道,專門用來管理來自外設對存儲器的訪問請求 ...
  • 1:打開任務管理器, [運行新任務] 2:(勾上以系統管理員許可權創建此任務) 輸入 cmd 3:進入要安裝的軟體所在的目錄:cd D:\111_安裝包\submit 3 (本文以安裝submit 為例子) 4:輸入命令:Sublime Text Build 3083 x64 Setup.exe 就會 ...
  • 定義這樣一個方法,然後接收前臺傳過來的值,調用這個方法就行了.. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...