MVC四大筛选器—ActionFilter&ResultedFilter
来源:互联网 发布:java初级工程师面试 编辑:程序博客网 时间:2024/06/07 22:41
AuthorizeFilter筛选器
在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行。
MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Action方法上标注相应的Attribute标签来实现。MVC4提供了四种筛选器,分别为:AuthorizationFilter、ActionFilter、ExceptionFilter和ResultFilter,他们分别对应了四个筛选器接口IAuthorizationFilter、IActionFilter、IExceptionFilter和IResultFilter。
这四种筛选器都有派生于一个公共的类FilterAttribute,该类指定了筛选器的执行顺序Order和是否允许多个应用AllowedMultiple。这四种筛选器默认的执行顺序为最先进行授权筛选,最后进行异常处理,中间则是ActionFilter和ResultedFilter。
下面是抽象类FilterAttribute的类图
下面我们来具体列举一下各个筛选器的作用和实现
从字面上我们就能看出这是对Controller或Action方法授权的筛选器,即在Controller或Action方法执行前,首先会先执行该筛选器,若通过,才会继续执行。下面是此筛选器的简单类图
AuthorizeAttribute为最终授权筛选器的实现者,它实现了IAuthorizationFilter接口和FilterAttribute抽象类,接口中的OnAuthorization(AuthorizationContext filterContext)方法是最终验证授权的逻辑(其中AuthorizationContext是继承了ControllerContext类)
protected virtual bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } IPrincipal user = httpContext.User; if (!user.Identity.IsAuthenticated) { return false; } if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) { return false; } if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)) { return false; } return true; }AuthorizeCore方法是最终OnAuthorization()方法调用的最终逻辑,从代码可以看出,当同时指定了users和roles时,两者只有同时满足条件时才可以验证授权通过。如
[Authorize(Users="zhangsan", Roles="Admin")] public ActionResult ActionMethod() { }
则只有用户zhangsan,且用户属于Admin角色时才能验证授权通过。
若验证不通过时,OnAuthorization方法内部会调用HandleUnauthorizedRequest
虚方法进行处理,代码如下:
protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs. filterContext.Result = new HttpUnauthorizedResult(); }
该方法设置了参数上下文中ActionResult的值,用于供View展示。
我们可以自定义Authorize筛选器,由于OnAthurization()、AuthorizeCore()和HandleUnauthorizedRequest()方法都是虚方法,我们自定义的Authorize筛选器只需要继承AuthorizeAttribute类,重写以上三种方法,这样就可以自定义自己的验证规则和验证失败时的处理逻辑了。
IAuthorizationFilter还有其他类型的实现类,如RequireHttpsAttribute、ValidateInputAttribute都是实现了OnAuthorization()方法,来完成各自筛选器处理的。
ExceptionFilter过滤器
该筛选器是在系统出现异常时触发,可以对抛出的异常进行处理。所有的ExceptionFilter筛选器都是实现自IExceptionFilter接口
public interface IExceptionFilter { void OnException(ExceptionContext filterContext); }
实现OnException方法来实现对异常的自定义处理
MVC4中实现了默认的异常处理机制,源码如下
public virtual void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (filterContext.IsChildAction) { return; } // If custom errors are disabled, we need to let the normal ASP.NET exception handler // execute so that the user can see useful debugging information. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { return; } Exception exception = filterContext.Exception; // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method), // ignore it. if (new HttpException(null, exception).GetHttpCode() != 500) { return; } if (!ExceptionType.IsInstanceOfType(exception)) { return; } string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); filterContext.Result = new ViewResult { ViewName = View, MasterName = Master, ViewData = new ViewDataDictionary<HandleErrorInfo>(model), TempData = filterContext.Controller.TempData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; // Certain versions of IIS will sometimes use their own error page when // they detect a server error. Setting this property indicates that we // want it to try to render ASP.NET MVC's error page instead. filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; }
Application_Start中将HandleErrorAttribute添加到全局筛选器GlobalFilterCollection中,系统即会对异常进行对应的处理。
我们现在实现一个自定义的异常处理筛选器,在处理完后记录异常信息至日志文件中
public class MyExceptionHandleAttribute : HandleErrorAttribute { public MyExceptionHandleAttribute() : base() { } public void OnException(ExceptionContext filterContext) { base.OnException(filterContext); //记录日志 log.Info(filterContext.Exception); } }
在GlobalFilterCollection添加MyExceptionHandleAttribute 即可使用自定义的异常筛选器来处理
ActionFilter筛选器
ActionFilter筛选器是在Action方法执行前后会触发,主要用于在Action执行前后处理一些相应的逻辑。ActionFilter的筛选器都继承于ActionFilterAttribute抽象类,而它实现了IActionFilter、IResultFilter和FilterAttribute类,结构如下
因此自定义ActionFilter筛选器只要继承ActionFilterAttribute,实现其中的方法即可。
我们来举一个简单的例子,获取Action方法的执行时长,代码如下
public class DefaultController : Controller { [ActionExecTimeSpan] public ActionResult DoWork() { return View(); } }public class ActionExecTimeSpanAttribute : ActionFilterAttribute { private const string executeActionTimeKey = "ActionExecBegin"; public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); //记录开始执行时间 filterContext.HttpContext.Items[executeActionTimeKey] = DateTime.Now; } public override void OnActionExecuted(ActionExecutedContext filterContext) { //计算执行时间,并记录日志 if (filterContext.HttpContext.Items.Contains(executeActionTimeKey)) { DateTime endTime = DateTime.Now; DateTime beginTime = Convert.ToDateTime(filterContext.HttpContext.Items[executeActionTimeKey]); TimeSpan span = endTime - beginTime; double execTimeSpan = span.TotalMilliseconds; log.Info(execTimeSpan + "毫秒"); } // base.OnActionExecuted(filterContext); } }
ResultFilter筛选器
ResultFilter筛选器是对Action方法返回的Result结果进行执行时触发的。它也分执行前和执行后两个段执行
所有的ResultFilter都实现了IResultFilter接口和FilterAttribute类,看一下接口定义
public interface IResultFilter { void OnResultExecuting(ResultExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext); }
其中OnResultExecuting和OnResultExecuted方法分别是在Result执行前、后(页面展示内容生成前、后)触发。使用ResultFilter筛选器最典型的应用就是页面静态化,我们以后在其他文章中在对此进行详细讲解
- MVC四大筛选器—ActionFilter&ResultedFilter
- ActionFilter for MVC asp.net
- Asp.Net MVC5代码的筛选器(ActionFilter)执行递归链表分析
- MVC中的筛选器
- asp.net mvc 之旅 —— 第六站 ActionFilter的应用及源码分析
- MVC 3.0 使用筛选器
- MVC 3.0 使用筛选器
- ASP.NET MVC筛选器之特殊筛选器IOverrideFilter
- asp.net mvc 1中ActionFilter的执行层级问题
- 在asp.net mvc中使用ActionFilter防止重复提交
- ASP.NET MVC 通过ActionFilter 实现AOP设计 示例
- asp.net core MVC 过滤器之ActionFilter过滤器(二)
- asp.net core MVC 过滤器之ActionFilter过滤器(二)
- asp.net core MVC 过滤器之ActionFilter过滤器(二)
- ActionFilter类
- 求教各位高手:ASP.net MVC使用ActionFilter判断访问页面的权限怎么实现?
- ASP.NET MVC 中的动态操作筛选器
- 深入探讨ASP.NET MVC的筛选器
- POJ 1469-COURSES(二分图匹配入门-匈牙利算法)
- 中医我还是持赞成的态度
- 浅析:setsockopt()改善socket网络程序的健壮性
- C语言字符输出格式化
- 堆排序代码
- MVC四大筛选器—ActionFilter&ResultedFilter
- 死者之魂推动遇难船
- 批处理基础
- 2016.8.17c组小结
- IO流——输出流(printStream和printWriter)
- [JZOJ4709] Matrix
- zzuli 1918 (宝藏 + 最大二分匹配 匈牙利算法)
- Android应用生死轮回的那些事儿(7) - PackageManager的不公开API
- DAY7