MVC四大筛选器—ActionFilter&ResultedFilter
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的更多相关文章
- MVC四大筛选器—AuthorizeFilter
在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行. MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Act ...
- MVC四大筛选器—ExceptionFilter
该筛选器是在系统出现异常时触发,可以对抛出的异常进行处理.所有的ExceptionFilter筛选器都是实现自IExceptionFilter接口 public interface IExceptio ...
- 在ASP.NET MVC中的四大筛选器(Filter)及验证实现
http://www.cnblogs.com/artech/archive/2012/08/06/action-filter.html http://www.cnblogs.com/ghhlyy/ar ...
- MVC常用筛选器Filter
1.ActionFilterAttribute using System; using System.Collections.Generic; using System.Diagnostics; us ...
- mvc 筛选器
之前公司中,运用ActionFilterAttribute特性实现用户登录信息的验证,没事看了看,留下点东西备忘. 好的,瞅这玩意一眼就大概能猜到这货是干嘛的了吧,没错,action过滤器.其实就是A ...
- Asp.Net mvc筛选器中返回信息中断操作
在mvc中,使用response.end()或Response.Redirect("url"); 是无法阻止请求继续往下执行的.如果在action中,可以我们可以使用return ...
- Asp.Net MVC 页面代码压缩筛选器-自定义删除无效内容
Asp.Net MVC 页面代码压缩筛选器 首先定义以下筛选器,用于代码压缩. /*页面压缩 筛选器*/ public class WhiteSpaceFilter : Stream { privat ...
- 基础教程:ASP.NET Core 2.0 MVC筛选器
问题 如何在ASP.NET Core的MVC请求管道之前和之后运行代码. 解 在一个空的项目中,更新 Startup 类以添加MVC的服务和中间件. publicvoid ConfigureServi ...
- 如何在ASP.NET MVC为Action定义筛选器
在ASP.NET MVC中,经常会用到[Required]等特性,在MVC中,同样可以为Action自定义筛选器,来描述控制器所遵守的规则. 首先,我们在ASP.NET MVC项目中定义一个TestC ...
随机推荐
- 2019.02.21 bzoj2300: [HAOI2011]防线修建(set+凸包)
传送门 题意:动态维护凸包周长. 思路: 见这篇求面积的吧反正都是一个套路. 代码: #include<bits/stdc++.h> #define int long long #defi ...
- Java生成静态HTML文件
private static final String FILEPATH = "/opt/nginx/html/banner/"; private static final Str ...
- HPS基本概念及其设计
DE1-SOC开发版上的FPGA在一个基于ARM的用户定制系统(SOC)中集成了分立处理器(HPS).FPGA和数字信号处理(DSP)功能.HPS是基于ARM cortex-A9双核处理器,具有丰富的 ...
- Android studio 中的TabWidget
1.TabWidget 的 layout文件 <?xml version="1.0" encoding="utf-8"?> <TabHost ...
- String str.trim()
String.trim() 方法不仅仅是去除字符串两端的空格字符,它能去除25种字符: ('/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', ...
- Javascript高级编程学习笔记(8)—— 变量
日常更新~~ 变量 所有的编程语言中,变量都是赋予语言灵活性的根本所在. 那么JS中的变量又有那些与众不同的地方呢.? 按照ECMA-262的定义,JS的变量和其他编程语言的变量有很大的区别 其松散类 ...
- Android开发工程师文集-1 小时学会各种Drawable
前言 大家好,给大家带来Android开发工程师文集-1 小时学会各种Drawable的概述,希望你们喜欢 Drawable介绍 Drawable为抽象类,drawable与view有区别的地方,主要 ...
- Win10下音频设备无法播放音乐问题定位
最近一直在调试音频设备,由于音频设备需要在不同的采样率下面转换,所以会经常导致我的win10无法播放和录音. 刚开始在网上搜了相关的知识,但是一直没找到有效的解决方案.后来,无奈之下,使用了微软的声音 ...
- linux系统添加swap(虚拟内存)分区
在实际的生产环境中,实际的物理内存我们经常会觉得不够用,增加物理内存的成本又比较高,一种折中方案就出来了,使用硬盘的一部分空间来做Swap(windows 下叫虚拟内存),将系统内非活动内存换页到 ...
- python(leetcode)-136只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...