ASP.NET MVC学习系列(4)——MVC过滤器FilterAttribute
1、概括
MVC提供的几种过滤器其实也是一种特性(Attribute),MVC支持的过滤器类型有四种,分别是:AuthorizationFilter(授权),ActionFilter(行为),ResultFilter(结果)和ExceptionFilter(异常),他们分别对应了四个筛选器接口IAuthorizationFilter、IActionFilter、IResultFilter和IExceptionFilter。这四种筛选器都有派生于一个公共的类FilterAttribute,该类指定了筛选器的执行顺序Order和是否允许多个应用AllowedMultiple。这四种筛选器默认的执行顺序为最先进行授权筛选,最后进行异常处理,中间则是ActionFilter和ResultedFilter。官网对FilterAttribute层次结构的介绍图如下
2、MVC四大过滤器介绍
2.1、AuthorizeFilter筛选器
AuthorizeAttribute为最终授权过滤器的实现者,它实现了IAuthorizationFilter接口和FilterAttribute抽象类,接口中的OnAuthorization(AuthorizationContext filterContext)方法是最终验证授权的逻辑(其中AuthorizationContext是继承了ControllerContext类),AuthorizeCore方法是最终OnAuthorization()方法调用的最终逻辑。
- bool AuthorizeCore(HttpContextBase httpContext):授权验证的逻辑处理,返回true则是通过授权,返回false则不是。若验证不通过时,OnAuthorization方法内部会调用HandleUnauthorizedRequest
- void HandleUnauthorizedRequest(AuthorizationContext filterContext):这个方法是处理授权失败的事情。
AuthorizeCore代码如下:
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 > && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
{
return false;
} if (_rolesSplit.Length > && !_rolesSplit.Any(user.IsInRole))
{
return false;
} return true;
}
我们不一定要用MVC默认的Authorize授权验证规则,规则可以自己来定,自定义授权过滤器继承IAuthorizeAttribute和FilterAttribute,由于OnAthurization()、AuthorizeCore()和HandleUnauthorizedRequest()方法都是虚方法,这些方法是可以重写的,这样就可以自定义自己的验证规则和验证失败时的处理逻辑了。示例代码如下
public class PermissionFilterAttribute: AuthorizationFilter
{ protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return true;
} protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result=""; }
}
授权过滤器的使用方式一如下:
[PermissionFilterAttribute]
public ActionResult index()
{
return View();
}
2.2、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);
}
}
2.3、ResultFilter过滤器
ResultFilter过滤器是对Action方法返回的Result结果进行执行时触发的。它也分执行前和执行后两个段执行,所有的ResultFilter都实现了IResultFilter接口和FilterAttribute类,看一下接口定义
public interface IResultFilter
{
void OnResultExecuting(ResultExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext);
}
其中OnResultExecuting和OnResultExecuted方法分别是在Result执行前、后(页面展示内容生成前、后)触发。使用ResultFilter筛选器最典型的应用就是页面静态化。
2.4、ExceptionFilter过滤器(详细介绍https://www.cnblogs.com/qtiger/p/10824562.html)
该过滤器是在系统出现异常时触发,可以对抛出的异常进行处理。所有的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() != )
{
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 = ; // 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中,系统即会对异常进行对应的处理。
3、其他的过滤器
3.1、OutputCache过滤器
表示一个特性,该特性用于标记将缓存其输出的操作方法。当用户访问页面时,整个页面将会被服务器保存在内存中,这样就对页面进行了缓存。当用户再次访问该页,
页面不会再次执行数据操作,页面首先会检查服务器中是否存在缓存,如果缓存存在,则直接从缓存中获取页面信息,如果页面不存在,则创建缓存。OutputCache的代码定义片段如下:
[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Method, Inherited = true,
AllowMultiple = false)]
public class OutputCacheAttribute : ActionFilterAttribute,
IExceptionFilter
从上面的代码中可以看到该特性可以应用在类,方法上面。在mvc中,就可以直接在控制器上面或者控制器中的Action上面直接使用,做到细粒度的对缓存的控制。
namespace OutputCacheDemo.Controllers
{
[OutputCache(Duration = )]
public class HomeController : Controller
{
// GET: Home
public string Index()
{
return DateTime.Now.ToString();
}
}
}
上面的代码是将OutputCache特性标记在了控制器类上,以达到该控制器上所有的Action都将应用该特性,过期时间设置为10s。10s后缓存过期,再访问就会更新时间。OutputCache特性也可以设置在Action方法上面,以达到更细粒度的控制缓存,代码如下:
public class HomeController : Controller
{
[OutputCache(Duration = )]
// GET: Home
public string Index()
{
return DateTime.Now.ToString();
}
}
此时,只有Index的页面进行了缓存。如果多个控制器或者Action使用相同的缓存配置,可以在配置文件中进行统一配置。
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles >
<add name='myoutputcache' duration=''/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
应用名称为myoutputcache的缓存代码如下:
public class HomeController : Controller
{
[OutputCache(CacheProfile = "myoutputcache")]
// GET: Home
public string Index()
{
return DateTime.Now.ToString();
}
}
注意:当控制器和Action同时使用了OutputCache特性时,以Action为主。
参考资料:https://www.cnblogs.com/wolf-sun/p/6219245.html
https://blog.csdn.net/zyh_1988/article/details/52234111
ASP.NET MVC学习系列(4)——MVC过滤器FilterAttribute的更多相关文章
- ASP.NET MVC学习系列(二)-WebAPI请求
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
- ASP.NET MVC学习系列(二)-WebAPI请求(转)
转自:http://www.cnblogs.com/babycool/p/3922738.html 继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的g ...
- [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参
[转]ASP.NET MVC学习系列(二)-WebAPI请求 传参 本文转自:http://www.cnblogs.com/babycool/p/3922738.html ASP.NET MVC学习系 ...
- ASP.NET MVC学习系列(二)-WebAPI请求 转载https://www.cnblogs.com/babycool/p/3922738.html
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
- MVC学习系列4--@helper辅助方法和用户自定义HTML方法
在HTML Helper,帮助类的帮助下,我们可以动态的创建HTML控件.HTML帮助类是在视图中,用来呈现HTML内容的.HTML帮助类是一个方法,它返回的是string类型的值. HTML帮助类, ...
- MVC学习系列——ModelBinder扩展
在MVC系统中,我们接受数据,运用的是ModelBinder 的技术. MVC学习系列——ActionResult扩展在这个系列中,我们自定义了XmlResult的返回结果. 那么是不是意味着能POS ...
- MVC学习系列——记一次失败面试后,感想。
在此写博客之际,热烈庆祝母校苏州科技学院,正式改名为苏州科技大学. 一晃眼,从自己投身IT行业已经两年有余,期间经历了结婚.买房等人生大事,非常感谢我的老婆,谢谢她这么爱我,嫁给我这个码农,呵呵... ...
- MVC学习一:MVC简单流程
MVC学习一:MVC初次接触 1.MVC简单流程 1.1.服务器接收客户端请求后,解析URL(根据 路由表里配置的URL来分析 类名(控制器名)和方法名)根据请求的类名,创建对应的控制器类对象,并调用 ...
- Asp.net MVC 学习系列(一)序
题外话 公司本月开始提供早餐服务,2块天一餐,包括粥,两个包(听说是利口福供应的),一个鸡蛋.良心企业.公司原本有一个内部订餐系统,用Delphi开发的,开发的人早就走光了,也没有留下什么文档,现在项 ...
随机推荐
- bind(),unbind(),hover(),toggle(),animate()
First.bind() bind(Type,fn) type:click/mouseover/mouseout fn:functionsecond.unbind() unbind(Type,fn) ...
- 开始使用Filebeat
认识Beats Beats是用于单用途数据托运人的平台.它们以轻量级代理的形式安装,并将来自成百上千台机器的数据发送到Logstash或Elasticsearch. (画外音:通俗地理解,就是采集数据 ...
- pymysql.err.InternalError: (1205, 'Lock wait timeout exceeded; try restarting transaction')错误处理
问题描述: 在使用pymysql库时,利用游标执行插入操作,产生错误,会出现pymysql.err.InternalError: (1205, 'Lock wait timeout exceeded; ...
- docker 复制镜像和复制容器
复制镜像和复制容器都是通过保存为新镜像而进行的. 具体为: 保存镜像 docker save ID > xxx.tar docker load < xxx.tar 保存容器 docker ...
- kubernetes进阶之六:StatefulSet & DaemonSet
StatefulSet(有状态): StatefulSet适合持久性的应用程序,有唯一的网络标识符(IP),持久存储,有序的部署,拓展,删除和滚动更新. 在Kubernetes系统中,Pod的管理对象 ...
- [Code+#3] 寻找车位
Description 给定一个大小为 \(n\times m\) 的 \(01\) 矩阵. 要求支持:单点翻转,询问子矩形内部最大正方形. \(n\times m\leq 4\cdot 10^6,n ...
- Shell编程(week4_day3)--技术流ken
本节内容 1. shell流程控制 2. for语句 3. while语句 4. break和continue语句 5. case语句 6. shell编程高级实战 shell流程控制 流程控制是改变 ...
- [转]nodeJs--koa2 REST API
本文转自:https://blog.csdn.net/davidPan1234/article/details/83413958 REST API规范编写REST API,实际上就是编写处理HTTP请 ...
- 基于C#程序设计语言的三种组合算法
目录 基于C#程序设计语言的三种组合算法 1. 总体思路 1.1 前言 1.2 算法思路 1.3 算法需要注意的点 2. 三种组合算法 2.1 普通组合算法 2.2 与自身进行组合的组合算法 2.3 ...
- Java开发笔记(三十四)字符串的赋值及类型转换
不管是基本的char字符型,还是包装字符类型Character,它们的每个变量只能存放一个字符,无法满足对一串字符的加工.为了能够直接操作一连串的字符,Java设计了专门的字符串类型String,该类 ...