這裡用實例說明各種過濾器的用法,有不對的地方還請大神指出,共同探討。 1. ActionFilter 方法過濾器: 介面名為 IActionFilter ,在控制器方法調用前/後執行。 在新建的MVC程式中,添加一個類 MyFilter1Attribute 並繼承ActionFilterAttrib ...
這裡用實例說明各種過濾器的用法,有不對的地方還請大神指出,共同探討。
1. ActionFilter 方法過濾器:
介面名為 IActionFilter ,在控制器方法調用前/後執行。
在新建的MVC程式中,添加一個類 MyFilter1Attribute 並繼承ActionFilterAttribute抽象類
從上圖可以看到 ActionFilterAttribute 中的所有方法,且有相應的介紹,我們可以通過繼承 ActionFilterAttribute 類,並重寫(override)它的方法,從而實現自定義Filter
public class MyFilter1Attribute: ActionFilterAttribute { /// <summary> /// 該方法會在Action方法執行之前調用 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在Ation方法調用前執行<br/>"); base.OnActionExecuting(filterContext); } /// <summary> /// 該方法會在Action方法執行之後調用 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("我是OnActionExecuted,我在Action方法調用後執行<br/>"); base.OnActionExecuted(filterContext); } }
然後創建一個HomeController控制器,並添加FilterTest的測試Action
public class HomeController : Controller { public ActionResult Index() { return View(); } [MyFilter1] public void FilterTest() { Response.Write("我是Action方法,我在這裡執行了.....<br/>"); } }
運行程式並訪問FilterTest方法:
上圖可看出它的一個執行順序
但是有時候也有可能有這樣的場景:當檢查到Action有標識某個Attribute的時候,我們需要跳出,並不執行後續的方法的情況,我們可以通過filterContext中ActionDescriptior類中的IsDefained方法進行判斷檢查
/// <summary> /// 該方法會在Action方法執行之前調用 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("我是OnActionExecuting,我在Ation方法調用前執行<br/>"); //判斷Action方法時是否有貼上MyFilter1Attribute標簽 if (filterContext.ActionDescriptor.IsDefined(typeof(MyFilter1Attribute), false)) { //如果有,為該Action方法直接返回ContentResult,則該Action方法在這裡就有了返回值,相當於在這裡就結束了,不會再去執行之後的方法,例如:OnActionExecuted filterContext.Result = new ContentResult(); } base.OnActionExecuting(filterContext); }
2.ResultFilter 結果過濾器:
介面名為 IResultFilter,在控制器方法調用完,跳轉至View頁面前/後調用
同樣在 MyFilter1Attribute 類中重寫 OnResultExecuting 方法和 OnResultExecuted 方法
/// <summary> /// 該方法在Action方法返回結果之前執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("我是OnResultExecuting,我在Action方法返回結果前執行<br/>"); base.OnResultExecuting(filterContext); } /// <summary> /// 該方法在Action方法返回結果之後執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("我是OnResultExecuted,我在Action方法返回結果後執行<br/>"); base.OnResultExecuted(filterContext); }View Code
然後在HomeController控制器中添加 FilterTest1
[MyFilter1] public ActionResult FilterTest1() { Response.Write("我是測試Action1方法,我在這裡執行了.....<br/>"); return View(); }View Code
運行程式,並訪問 FilterTest1 ,執行結果如下:
可以看出OnResultExecuting 方法是在返回結果頁面之前執行的,而OnResultExecuted是返回結果頁面之後執行的
3.ExceptionFilter 異常操作過濾器:
介面名為 IExceptionFilter,在控制器的Action方法拋出異常時執行
可以通過異常過濾器捕獲Controller中發生的異常,並記錄到日誌。
添加MyExceptionAttribute類,並繼承HandleErrorAttribute,如下:
/// <summary> /// /// </summary> /// <param name="filterContext"></param> public override void OnException(ExceptionContext filterContext) { filterContext.HttpContext.Response.Write("我是OnException,在Controller中發生異常時進入<br/>"); //獲取到異常對象 Exception ex = filterContext.Exception; //獲取請求的Controller和Action string controllerName = filterContext.RouteData.Values["controller"].ToString(); string actionName = filterContext.RouteData.Values["action"].ToString(); //記錄日誌 string errMessage = string.Format("異常消息:控制器為:{0},Action為:{1},異常信息為:{2};", controllerName, actionName, ex.Message); OutPutLog(errMessage); //標記異常已做處理 filterContext.ExceptionHandled = true; base.OnException(filterContext); } /// <summary> /// 輸出日誌 /// </summary> /// <param name="message"></param> public void OutPutLog(string message) { string path = AppDomain.CurrentDomain.BaseDirectory + "/Logs.txt"; using (StreamWriter sw = new StreamWriter(path, true, Encoding.Default)) { sw.Flush(); sw.WriteLine("時間:" + DateTime.Now); sw.WriteLine("內容:" + message); sw.WriteLine("---------------------------------------------"); } }View Code
在HomeController中添加FilterTest3
[MyException] public ActionResult FilterTest3() { Response.Write("我是測試Action3方法,我在這裡執行了.....<br/>"); string str = "131464ddddd"; int i = int.Parse(str); return View(); }
運行程式並訪問 FilterTest3方法,將會在 str 轉換成int類型時拋出異常,隨後將進入OnException方法,並記錄日誌如下:
4.AuthorizationFilter 授權過濾器:
介面名為 IauthorizationFilter,在所有過濾器中最先執行
添加一個MyFilter2Attribute類,並繼承AuthorizeAttribute類,然後重寫其OnAuthorization方法:
public class MyFilter2Attribute: AuthorizeAttribute
{
/// <summary>
/// 在所有的Action方法過濾之前執行
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.HttpContext.Response.Write("我是OnAuthorization,在所有Action方法過濾器之前執行<br/>");//base.OnAuthorization(filterContext);
}
}
在HoneController控制器中添加 FilterTest2
[MyFilter1]
[MyFilter2]
public ActionResult FilterTest2()
{
Response.Write("我是測試Action2方法,我在這裡執行了.....<br/>");
return View();
}
運行程式並訪問 FilterTest2 結果如下:
從上圖執行結果可以看出,OnAuthorization 權重是最高的,將會在其他所有過濾器之前執行。
註意:
ActionFilter 和 ResultFilter 不僅可以對單個方法進行操作,也能對整個Controller進行操作,將過濾的頭部屬性移至控制名稱上面即可。