2010年7月21日 星期三

ASP.NET MVC 之 ActionFilterAttribute

我們常常會在 Action 或是 Controller 上面看到黏了一些東西,像下面這樣:
[HttpPost]
public ActionResult Test(FormCollection testFormCollection)
{
    string Name = testFormCollection["Name"];
    string Title = testFormCollection["Title"];
    return View();
}
那個 [HttpPost] 就是我們說的 Attribute,
這可以做些什麼呢?
其實可以做的事情可多了,像是在 Action 執行前做些前處理的事情,
或是 Action 執行後做,而且很多 Action 都會用到的話,
那用 Attribute 來處理,是相當不錯的選擇。

實作上相當簡單,只要你寫個類別繼承 ActionFilterAttribute 這個抽象類別即可。

ActionFilterAttribute 這抽象類別主要有四個方法可以被覆寫:
1.OnActionExecuting
來自 IActionFilter 介面,於 Action Method 執行前,被呼叫。
2.OnActionExecuted
來自 IActionFilter 介面,於 Action Method 執行後,被呼叫。
3.OnResultExecuting
來自 IResultFilter 介面,於 Result Method 執行前,被呼叫。
4.OnResultExecuted
來自 IResultFilter 介面,於 Result Method 執行後,被呼叫。

這邊我們嘗試做一個 Form 驗證的 Attribute,
使含有不合法的字串的 Request,回應 302 Found。
using System.Collections.Specialized;
using System.Web.Mvc;

namespace MvcApplication1.Mvc.Attributes
{
    public class ValidateForm : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            NameValueCollection waitValidate = filterContext.HttpContext.Request.Form;
            for (int i = 0; i < waitValidate.Count; i++)
            {
                if (IsIllegalString(waitValidate[i].ToString()))
                {
                    filterContext.HttpContext.Response.Status = "302 Found";
                    break;
                }
            }
        }

        private bool IsIllegalString(string waitCheck)
        {
            string[] pattern = 
            { 
                "--", ";", "/*", "*/", "@@", "char", "nchar", "varchar", 
                "nvarchar", "alter", "begin", "cast", "create", "cursor", "declare",
                "delete", "drop", "end", "exec", "execute", "fetch", "insert", "kill",
                "open", "select", "sys", "sysobjects", "syscolumns", "table", "update"
            };
            foreach (string item in pattern)
            {
                if (waitCheck.ToLower().Contains(item))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
然後我們在要處理的 Action 上,加上這個 Attribute,像下面這樣:
[HttpPost, ValidateForm]
public ActionResult About()
{
    return View();
}
接著找個 View 建立一個 Form 將資料 Post 給 About 這個 Action,像下面這樣:


執行畫面:


送出後,用 Firebug 查看,發現 Http Status 被改了!
如果輸入字串中並沒有任何 pattern 裡面的字串的話則會收到 200 OK


這樣就完成任務啦,Attribute 有很多應用面,比方說使用者的操作紀錄,
或是權限驗證與檢查等等,都是可以發揮的地方。
此範例可以將 Http Status 設為 302 Found 那邊換成你想要處理的邏輯。


沒有留言: