ASP.NET MVC中Filter過濾器的使用
MVC Filter是典型的AOP(面向切面程式設計)應用,在ASP.NET MVC中的4個過濾器型別,如下:
過濾器型別 | 介面 | 預設實現 | 描述 |
---|---|---|---|
Action | IActionFilter | ActionFilterAttribute | 在動作方法之前及之後執行 |
Result | IResultFilter | ActionFilterAttribute | 在動作結果被執行之前和之後執行 |
AuthorizationFilter | IAuthorizationFilter | AuthorizeAttribute | 首先執行,在任何其它過濾器或動作方法之前 |
Exception | IExceptionFilter | HandleErrorAttribute | 只在另一個過濾器、動作方法、動作結果彈出異常時執行 |
但是預設實現它們的過濾器只有三種,分別是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());
}
}