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); } } }