[ASP.NET MVC] 客製 ActionFilterAttribute

前言

ASP.NET MVC 提供 ActionFilterAttribute 抽象類別,讓開發人員在 Action 執行之前或執行之後,可以注入自己的客製程式,例如寫入 LOG。以下紀錄它的用法。

客製 ActionFilterAttribute

1. 命名

在 ASP.NET 約定的用法,ActionFilterAttribute 的命名是在自訂名稱尾端加上「Attribute」,例如,HelloWorldAttribute。調用它時,可以這樣寫:[ HelloWorld ]或[ HelloWorldAttribute ]。

2. 自訂類別繼承 ActionFilterAttribute

ActionFilterAttribute 有四種虛擬方法,可讓我們覆寫:

  • OnActionExecuting – 執行 Action 之前執行
  • OnActionExecuted – 執行 Action 之後執行
  • OnResultExecuting – 執行 Action Result 之前執行
  • OnResultExecuted – 執行 Action Result 之後執行

假設我們寫一個繼承自 ActionFilterAttribute 的 HelloWorldAttribute 類別。在它的建構式,我們可以定義要輸入甚麼樣的參數。

參數有兩種定義方式:一是值參數、一是定位參數 (position parameter)。在 HelloWorldAttribute 建構式中我們定義兩個值參數,namd, id。

public string Name { get; set; }
public int ID { get; set; }
public Drinks OrderDrink{get;set;} //注意這個 Property

public HelloWorldAttribute(string name, int id)
{
    this.Name = name;
    this.ID = id;
}

我們另外定義一個列舉 Drinks

public enum Drinks
{
    TEA,
    CAFE,
    WATER
}

以上這兩種定義有不同的參數寫法。

3. 完整範例

public enum Drinks
{
    TEA,
    CAFE,
    WATER
}

public class HelloWorldAttribute : ActionFilterAttribute
{  
    public string Name { get; set; }
    public int ID { get; set; }
    public Drinks OrderDrink{get;set;} //注意這個 Property

    public HelloWorldAttribute(string name, int id)
    {
        this.Name = name;
        this.ID = id;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }

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

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
         string n = this.Name;
         string drinks = this.OrderDrink.ToString();
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        base.OnResultExecuting(filterContext);
    } 
}

在 Controller 注入

我們在 Controller 的 Action 注入 HelloWorldAttribute。可以看到前面兩個參數「jeff」、「5」 分別是上面定義的 HelloWorldAttribute 建構式的兩個參數:「name」、「id」。

第三個參數是所謂的定位參數,利用HelloWorldAttribute 類別定義好的 Property :OrderDrink ,指定一個 enum 的值。雖然在建構式並未定義。

public class HomeController : Controller
{
    [HelloWorld("Jeff", 5, OrderDrink = Drinks.CAFE)] //注意 OrderDrink = Drinks.CAFE
    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }
}

如此一來,當執行 About 這個 Action,會先執行 HelloWorldAttribute 的方法 OnResultExecuted()。

(文章若有錯誤,歡迎指教。)

發表留言