9-2.ASP.NET MVC中Filter過濾器的使用
https://blog.csdn.net/pan_junbiao/article/details/84523935
MVC Filter是典型的AOP(面向切面程式設計)應用,在ASP.NET MVC中的4個過濾器型別,如下:
但是預設實現它們的過濾器只有三種,分別是ActionFilter(方法),Authorize(授權),HandleError(錯誤處理)。
1、Action過濾器
在ASP.NET MVC中建立MvcApp專案,建立資料夾Filter,然後新建類MyActionFilterAttribute(為了遵循預設的約定,名稱以Attribute結尾),繼承自ActionFilterAttribute類。ActionFilterAttribute類有如下4個方法。
using System; namespace System.Web.Mvc { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter { protected ActionFilterAttribute();public virtual void OnActionExecuted(ActionExecutedContext filterContext); public virtual void OnActionExecuting(ActionExecutingContext filterContext); public virtual void OnResultExecuted(ResultExecutedContext filterContext); public virtual void OnResultExecuting(ResultExecutingContext filterContext); } }
實現MyActionFilterAttribute類:
using System; using System.Web.Mvc; namespace MvcApp.Filter { public class MyActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { //1、獲取請求的類名和方法名 string strController = filterContext.RouteData.Values["controller"].ToString(); string strAction = filterContext.RouteData.Values["action"].ToString(); //2、用另一種方式獲取請求的類名和方法名 string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; string strAction2 = filterContext.ActionDescriptor.ActionName; filterContext.HttpContext.Response.Write("控制器:" + strController + "<br/>"); filterContext.HttpContext.Response.Write("控制器:" + strController2 + "<br/>"); filterContext.HttpContext.Response.Write("Action:" + strAction + "<br/>"); filterContext.HttpContext.Response.Write("Action:" + strAction2 + "<br/>"); filterContext.HttpContext.Response.Write("Action執行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>"); base.OnActionExecuting(filterContext); } public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("Action執行後:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>"); base.OnActionExecuted(filterContext); } } }
對於過濾器,我們可以把它們加在3個地方,一個是控制器上面(控制器下面的所有Action),一個是Action上面(指定標識的Action),另一個就是全域性位置(所有控制器中的Action)。這裡只演示在Action上面和Home控制器中:
[MyActionFilter] public ActionResult Index() { return View(); }
2、Result過濾器
新建MyResultFilterAttribute類,繼承ActionFilterAttribute:
using System; using System.Web.Mvc; namespace MvcApp.Filter { public class MyResultFilterAttribute : ActionFilterAttribute { /// <summary> /// 載入“檢視”前執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.HttpContext.Response.Write("載入檢視前執行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>"); base.OnResultExecuting(filterContext); } /// <summary> /// 載入“檢視”後執行 /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Write("載入檢視後執行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>"); base.OnResultExecuted(filterContext); } } }
這裡把MyResultFilter過濾器加在控制器上面,相當於給Home控制器中的所有的Action方法添加了MyResultFilter過濾器。
using MvcApp.Filter; using System.Web.Mvc; namespace MvcApp.Controllers { [MyResultFilter] public class HomeController : Controller { [MyActionFilter] public ActionResult Index() { return View(); } } }
3、AuthorizeAttribute過濾器
建立MyAuthorizeAttribute類,繼承AuthorizeAttribute類:
using System.Web.Mvc; namespace MvcApp.Filter { /// <summary> /// 授權過濾器 /// </summary> public class MyAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { filterContext.HttpContext.Response.Write("OnAuthorization<br/>"); //註釋掉父類方法,因為父類裡的OnAuthorization方法會呼叫ASP.NET的授權驗證機制 //base.OnAuthorization(filterContext); } } }
在控制器Home中的Index上新增MyAuthorize過濾器:
[MyAuthorize] [MyActionFilter] public ActionResult Index() { return View(); }
通常Authorize過濾器也是在全局過濾器上面的,主要用來做登入驗證或者許可權驗證,在App_Start目錄下的FilterConfig類的RegisterGlobalFilters方法中新增:
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); //新增全域性授權過濾器 filters.Add(new MyAuthorizeAttribute()); } }
在全域性中註冊過濾器,則所有控制器的所有行為(Action)都會執行這個過濾器。
執行結果,如下圖:
4、Exception過濾器
建立MyHandleErrorAttribute類,繼承HandleErrorAttribute類:
using System; using System.Web.Mvc; namespace MvcApp.Filter { /// <summary> /// 異常處理過濾器 /// </summary> public class MyHandleErrorAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { //1、獲取異常物件 Exception ex = filterContext.Exception; //2、記錄異常日誌 //3、重定向友好頁面 filterContext.Result = new RedirectResult("~/error.html"); //4、標記異常已經處理完畢 filterContext.ExceptionHandled = true; base.OnException(filterContext); } } }
在Action上面新增MyHandleError過濾器:
[MyHandleError] public ActionResult GetErr() { int a = 0; int b = 1 / a; return View(); }
建立異常錯誤友好提示頁面error.html。
<body>
自定義錯誤頁面
</body>
執行會自動跳轉到error.html頁面。
如果頁面沒有跳轉,就需要去Web.config配置檔案中的<system.web>節點下面新增如下配置節點,開啟自定義錯誤:
<customErrors mode="On"></customErrors>
通常這樣的異常處理是放在全域性過濾器上面的,只要任意Action方法報錯就會執行MyHandleError過濾器中的程式碼。
修改App_Start目錄下面的FilterConfig類:
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); //新增全域性授權過濾器 filters.Add(new MyAuthorizeAttribute()); //新增全域性異常處理過濾器 filters.Add(new MyHandleErrorAttribute()); } }
Global.asax下的程式碼:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace MvcApp { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } }