asp.net MVC之 自定义过滤器(Filter)
一、系统过滤器使用说明
1、OutputCache过滤器
OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数。它有以下属性:
Duration:缓存的时间,以秒为单位,理论上缓存时间可以很长,但实际上当系统资源紧张时,缓存空间还是会被系统收回。
VaryByParam:以哪个字段为标识来缓存数据,比如当“ID”字段变化时,需要改变缓存(仍可保留原来的缓存),那么应该设VaryByParam为"ID"。这里你可以设置以下几个值:
- * = 任何参数变化时,都改变缓存。
- none = 不改变缓存。
以分号“;”为间隔的字段名列表 = 列表中的字段发生变化,则改变缓存。
Location:缓存数据放在何处。缓存位置很重要,如果存在服务器上,那么所有用户看到的缓存视图都会一样,如果存在客户端,那么用户只会看到自己的缓存。比如:如果是一些私人信息,那就不能存在服务器上。你可以设置以下值:
- · Any :默认值,输出缓存可位于产生请求的浏览器客户端、参与请求的代理服务器(或任何其他服务器)或处理请求的服务器上。
- · Client:输出缓存位于产生请求的浏览器客户端上。
- · Downstream 输出缓存可存储在任何 HTTP 1.1 可缓存设备中,源服务器除外。这包括代理服务器和发出请求的客户端。
- · Server:输出缓存位于处理请求的 Web 服务器上。
- · None:对于请求的页,禁用输出缓存。
- · ServerAndClient:输出缓存只能存储在源服务器或发出请求的客户端中。代理服务器不能缓存响应。
- NoStore:该属性定义一个布尔值,用于决定是否阻止敏感信息的二级存储。
以下给出一个简单的例子,在页面上显示一个时间,设置缓存为10秒,在10秒刷新,输出的值都不会改变。
[OutputCache(Duration=5)]public ActionResult Index(string name){return Content(DateTime.Now.ToString());}
除了直接在Action或者类的定义前加上属性,也可以使用配置文件,这样就可以动态配置你的缓存模式了。
在<system.web>节中,添加如下配置:
<outputCacheSettings><outputCacheProfiles><add name="Cache1Hour" duration="3600" varyByParam="none"/></outputCacheProfiles> </outputCacheSettings> </caching>
那么在Controller中可以这样使用:
[OutputCache(CacheProfile="Cache1Hour")] public string Index() {return DateTime.Now.ToString("T"); }
[扩展]在已经缓存的页面上添加动态内容
为了提高用户体验,我们会使用缓存技术,但是有时我们会需要在页面上改变内容,如:提供一些动态信息、广告的变化等。
此时我们可以调用 HttpResponse.WriteSubstitution() 方法。
@Response.WriteSubstitution(News.RenderNews);
其中News.RenderNews是一个静态方法,它的定义如下,这个方法用来随机显示三条广告词。
public class News {public static string RenderNews(HttpContext context){var news = new List<string> { "Gas prices go up!", "Life discovered on Mars!", "Moon disappears!" };var rnd = new Random();return news[rnd.Next(news.Count)];} }
将Response.WriteSubstitution()写成扩展方法的示例:
public static class AdHelper{public static void RenderBanner(this HtmlHelper helper){var context = helper.ViewContext.HttpContext;context.Response.WriteSubstitution(RenderBannerInternal);}private static string RenderBannerInternal(HttpContext context){var ads = new List<string> { "/ads/banner1.gif", "/ads/banner2.gif", "/ads/banner3.gif" };var rnd = new Random();var ad = ads[rnd.Next(ads.Count)];return String.Format("<img src='{0}' />", ad);}}
调用方法如下:
<% Html.RenderBanner(); %>
2、ActionName
ActionName用于规定Action的名称,当使用此过滤器后,MVC将不再理会路径中的Action名称,而是用标记中的ActionName代替方法名中的ActionName。例如:
[ActionName("关于")] public ActionResult About() {return View(); }
此时,当访问/Home/About时匹配不到Action,需要访问/Home/关于才能访问该Action,并且使用的是名为"关于"的视图。
3、NonAction
NonAction标记一个Action只是一个普通的方法,不作为MVC的Action。如:
public class HomeController : Controller{[NonAction]public ActionResult Index(string name){return Content(DateTime.Now.ToString());}}
此时访问/Home/Index将找不到Action。
4、RequireHttps
强制使用Https重新发送请求;如:
public class HomeController : Controller{[RequireHttps]public ActionResult Index(string name){return Content(DateTime.Now.ToString());}}
如果请求:http://localhost/Home/Index 将跳转到 https://localhost/Home/Index。
5、ValidateInput
该Action是否过滤Html等危险代码(ASP.NET MVC在aspx中设置<%@ Page 的属性无法完成等同任务。)
如以下代码:
public class HomeController : Controller{[ValidateInput(true)]public ActionResult Index(string name){return Content(DateTime.Now.ToString());}}
上述代码表示开启安全验证,当输入以下路径时:
http://localhost:3833/home/index?name=%3Ca%3E123%3C/a%3E //http://localhost:3833/home/index?name=<a>123</a>
程序报如下错误:
“/”应用程序中的服务器错误。
从客户端(name="<a>123</a>")中检测到有潜在危险的 Request.QueryString 值。
6、AllowHtml
AllowHtml用于禁用某个字段、属性的验证,则可以使用MVC3中的AllowHtml属性实现。如:
namespace Mvc权限控制.Controllers {public class HomeController : Controller{public ActionResult Index(Content c){return View(); ;}}public class Content{public int Id { get; set; }[AllowHtml]public string Body { get; set; }} }
页面代码:
<body><div><form action="/Home/Index" method="post">请输入Id:<input type="text" name="Id" />请输入姓名:<input type="text" name="Body" /><input type="submit" value="提交" /></form></div> </body>
注意,如果将上面Body的属性AllowHtml标记去掉,将报如下错误:
“/”应用程序中的服务器错误。
从客户端(Body="<a>123</a>")中检测到有潜在危险的 Request.Form 值。
7、SessionState自定义Session控制
SessionState只能应用于Controller,不能作用于某一个Action。可选值如下:
- Default = 0,使用默认 ASP.NET 逻辑来确定请求的会话状态行为。默认逻辑是寻找 System.Web.IHttpHandler 中是否存在标记会话状态接口。
- Required = 1,为请求启用完全的读写会话状态行为。此设置将覆盖已通过检查请求的处理程序确定的任何会话行为。
- ReadOnly = 2,为请求启用只读会话状态。这意味着会话状态无法更新。此设置将覆盖已通过检查请求的处理程序确定的任何会话状态行为。
- Disabled = 3,未启用会话状态来处理请求。此设置将覆盖已通过检查请求的处理程序确定的任何会话行为。
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
8、Http动作过滤器
[HttpGet] [HttpSet] [HttpDelete] [HttpPut] 此4个过滤器用于筛选Http请求,[HttpGet]只处理Get请求,[HttpPost]只处理Post请求,[HttpDelete]只处理Delete请求,[HttpPut]只处理put请求。
9、ValidateAntiForgeryToken
防止跨站请求攻击时会在cookie添加一个随机项,然后添加一个随机数到表单里的<input type="hidden" />而ValidateAntiForgeryToken就是用于检测两项是否相等。主要包括:
(1)请求的是否包含一个约定的AntiForgery名的cookie
(2)请求是否有一个Request.Form["约定的AntiForgery名"],约定的AntiForgery名的cookie和Request.Form值是否匹配。
10.AsyncTimeout
异步访问过期设置
11.HandleError 错误过滤器
HandleErrorAttribute中,提供了4种基本属性:
- ExceptionType:指定处理的异常类型
- View:指定显示的View
- Master:指定要套用的Master页面
- Order:设置执行的顺序
12.AllowAnonymous
身份验证过滤器,允许匿名用户访问
13.ChildActionOnly
声明该Action不能直接通过Url 访问但可以作为某一个Action的子Action访问。
二、过滤器的类别以及执行顺序:
在Asp.net MVC中一共有4种过滤器,并且按照如下顺序依次执行。
- 授权筛选器:AuthorizationFilters
- 动作筛选器:ActionFilters
- 响应筛选器:ResultFilters
- 异常筛选器:ExceptionFilters
Controller最终是通过Controller的ExecuteCore完成的,这个方法通过调用ControllerActionInvoker的InvodeAction方法完成最终对于Action的调用。
其时序图如下:
三、自定义过滤器接口
ActionFilterAttribute的定义如下,允许我们在Action执行之前或者之后,在Action的返回结果被处理之前或者之后进行自定义处理。
using System; namespace System.Web.Mvc {[AttrubiteUsage(ArrtibuteTargets.Class | AttributeTargets.Method,Inherited = true,AllowMultiple = false)]public abstract class ActionFilterAttribute : FilterAttribute,IActionFilter,IResultFilter {public virtual void OnActionExecuting(ActionExecutingContext filterContext){}public virtual void OnActionExecuted(ActionExecutedContext filterContext){}public virtual void OnResultExecuting(ResultExecutingContext filterContext){}public virtual void OnResultExecuted(ResultExecutedContext filterContext){}} }
我们需要实现IActionFilter接口:
public interface IActionFilter {void OnActionExecuting(ActionExecutingContext filterContext);void OnActionExecuted(ActionExecutedContext filterContext); }
对于ResultFilter来说,我们需要实现接口IResultFilter
public interface IResultFilter {void OnResultExecuting(ResultExecutingContext filterContext);void OnResultExecuted(ResultExecutedContext filterContext); }
AuthorizationFilter和ExceptionFilter都比较简单,只有一个方法。
public interface IAuthorizationFilter {void OnAuthorization(AuthorizationContext filterContext); } public interface IExceptionFilter {void OnException(ExceptionContext filterContext); }
1、自定义Filter
自定义Filter需要继承ActionFilterAttribute抽象类,重写其中需要的方法,来看下ActionFilterAttribute类的方法签名。
//表示所有操作-筛选器特性的基类。[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter{protected ActionFilterAttribute();// 在Action执行之后由 MVC 框架调用。public virtual void OnActionExecuted(ActionExecutedContext filterContext);// 在Action执行之前由 MVC 框架调用。public virtual void OnActionExecuting(ActionExecutingContext filterContext);// 在执行Result后由 MVC 框架调用。public virtual void OnResultExecuted(ResultExecutedContext filterContext);// 在执行Result之前由 MVC 框架调用。public virtual void OnResultExecuting(ResultExecutingContext filterContext);}
因此自定义过滤器可以选择适当的方法来重写方可。下面来举个简单的例子:检查登录状态的过滤器,没有登录则跳转到登录页
控制器代码:
[CheckLogin] //此处为自定义属性,要引用相应的命名空间 public ActionResult Index() {return View(); }public ActionResult Login() //此Action自动往cookie里写入登录信息 {HttpCookie hcUserName = new HttpCookie("username","admin");HttpCookie hcPassWord = new HttpCookie("password","123456");System.Web.HttpContext.Current.Response.SetCookie(hcUserName);System.Web.HttpContext.Current.Response.SetCookie(hcPassWord);return View(); }
过滤器代码:
public class CheckLogin : ActionFilterAttribute{//在Action执行之前 乱了点,其实只是判断Cookie用户名密码正不正确而已而已。public override void OnActionExecuting(ActionExecutingContext filterContext){HttpCookieCollection CookieCollect = System.Web.HttpContext.Current.Request.Cookies;if (CookieCollect["username"] == null || CookieCollect["password"] == null){filterContext.Result = new RedirectResult("/Home/Login");}else{if (CookieCollect["username"].Value != "admin" && CookieCollect["password"].Value != "123456"){filterContext.Result = new RedirectResult("/Home/Login");}}}}//本示例贪图方便,将要跳转到的Action放在同一个Controller下了,如果将过滤器放到Controller类顶部,则永远也跳不到这个LoginAction。
此过滤器实现的效果是,当用户Cookie中用户名和密码不正确则跳转到登录页,注意过滤器也可以放在整个Controller类的顶部,表示该Controller下的所有Action都执行该项检查。这样一来,控制器里的代码非常漂亮,再也不用所有的Action里都充斥着判断登录的代码了。
2、带参数的自定义Filter
首先,还是按照之前添加自定义过滤器的方法,添加一个自定义过滤器,只是里面多了一个属性,代码如下:
public class FilterAttribute : ActionFilterAttribute{public string Message { get; set; }public override void OnActionExecuting(ActionExecutingContext filterContext){base.OnActionExecuting(filterContext);filterContext.HttpContext.Response.Write("Action执行之前" + Message + "<br />");}public override void OnActionExecuted(ActionExecutedContext filterContext){base.OnActionExecuted(filterContext);filterContext.HttpContext.Response.Write("Action执行之后" + Message + "<br />");}public override void OnResultExecuting(ResultExecutingContext filterContext){base.OnResultExecuting(filterContext);filterContext.HttpContext.Response.Write("返回Result之前" + Message + "<br />");}public override void OnResultExecuted(ResultExecutedContext filterContext){base.OnResultExecuted(filterContext);filterContext.HttpContext.Response.Write("返回Result之后" + Message + "<br />");}}
然后在调用过滤器的时候,添加上该参数,Controller代码如下:
[Filter(Message="刘备")] //参数给上public ActionResult Index(){return View();}
输出结果如下:
如果标签打到Controller上的话,TestFilterAttributeFilter将作用到Controller下的所有的Action。
默认情况下Action上打了某个自定义标签后,虽然在Controller上也打上了此标签,但它只有Action上的标签起作用了。
补充:如果Action没有打上该标签,那么Controller上的标签便会被执行。
如果想让Action上的标签执行一次,然后Controller上的标签也执行一次,那么应该如何操作呢?
我们只需在FilterAttribute类的定义上打上标记[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]即可【下面类的最上面红色字体部分】,也就是让其成为可以多次执行的Action。代码如下:
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)]public class FilterAttribute : ActionFilterAttribute{public string Message { get; set; }......}
3、全局过滤器
有时我们想有些公共的方法需要每个Action都执行,但是又不想再每一个Controller上都打上Action标签,怎么办?幸好Asp。Net MVC3带来了一个美好的东西,全局Filter。而怎么注册全局Filter呢?答案就在Global.asax中。让我们看以下代码,我是如何将上面我们定义的TestFilterAttribute 注册到全局Filter中。
public static void RegisterGlobalFilters(GlobalFilterCollection filters){filters.Add(new HandleErrorAttribute());//注册全局过滤器filters.Add(new TestFilterAttribute() { Message="全局"});}
这样就每个Action都会执行此过滤器,而不必每个Controller顶部都加上标签。
关注 - 22
粉丝 - 104
» 下一篇:Process类 进程管理器Demo
asp.net MVC之 自定义过滤器(Filter)相关推荐
- ASP.NET MVC ActionFilter自定义过滤器异常过滤器过滤器用法
自定义过滤器使用非常灵活,可以精确的注入到请求前.请求中和请求后.继承抽象类ActionFilterAttribute并重写里面的方法即可: public class SystemLogAttribu ...
- ASP.NET MVC使用Authorize过滤器验证用户登录
ASP.NET MVC使用Authorize过滤器验证用户登录.Authorize过滤器首先运行在任何其它过滤器或动作方法之前,主要用来做登录验证或者权限验证. 示例:使用Authorize过滤器实现 ...
- [Asp.net MVC]HandleErrorAttribute异常过滤器
[Asp.net MVC]HandleErrorAttribute异常过滤器 参考文章: (1)[Asp.net MVC]HandleErrorAttribute异常过滤器 (2)https://ww ...
- ASP.NET MVC 4 (三) 过滤器
先来看看一个例子演示过滤器有什么用: public class AdminController : Controller { // ... instance variables and constru ...
- [ASP.NET MVC] 利用自定义的AuthenticationFilter实现Basic认证
很多情况下目标Action方法都要求在一个安全上下文中被执行,这里所谓的安全上下文主要指的是当前请求者是一个经过授权的用户.授权的本质就是让用户在他许可的权限范围内做他能够做的事情,授权的前提是请求者 ...
- MVC之 自定义过滤器(ActionFilterAttribute)
一.自定义Filter 自定义Filter需要继承ActionFilterAttribute抽象类,重写其中需要的方法,来看下ActionFilterAttribute类的方法签名. //表示所有操作 ...
- ASP.NET MVC: 使用自定义 ModelBinder 过滤敏感信息
昨天发表了一篇随笔<ASP.NET MVC: 使用 Filters 附加过滤敏感信息功能>(以下简称<Filter过滤>),今天一早醒来发现一处重大漏洞,于是在发了一条评论指出 ...
- 【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链 (转)
你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你的服务器带宽.下面这种方法可以告诉你如何在ASP.NET MVC中实现一个自定义Ro ...
- ASP.NET MVC - 设置自定义IIdentity或IPrincipal
我需要做一些相当简单的事情:在我的ASP.NET MVC应用程序中,我想设置一个自定义IIdentity / IPrincipal. 哪个更容易/更合适. 我想扩展默认值,以便我可以调用User.Id ...
最新文章
- Java绘制基本图形
- 【OfficeDIY】有了站点了 ^_^
- java绘制地球绕太阳转_Unity3D 公转小案例:地球围绕太阳转
- linux 下串口的配置需要注意
- DL之MaskR-CNN:Mask R-CNN算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
- getopts命令行参数处理
- 浅析 React Fiber
- mybatis 带分号批量sql_请查收,32 道 MyBatis 的高频面试题已答完
- 关于MFC对话框程序如何接收命令行传递过来的参数问题
- FreeMarker语言【页面静态】
- 测试用例(测试大纲法)
- VMware ESXi Server 许可证注册方式
- 《好战略,坏战略》 摘记
- mac卸载java1.7_Mac 下安装、卸载Java 7
- 2022-2028年中国高通量药物筛选与创新药物行业市场调查研究及发展前景展望报告
- DDR SDRAM内存测试的一种官方方案(简单易懂)
- HYSBZ 2818 Gcd
- Access denied for user ‘root‘@‘localhost‘
- Python基础学习笔记:匿名函数
- 达梦数据库dm7同构数据库的双向同步
热门文章
- Codeforces 583 DIV2 Robot's Task 贪心
- 程序执行系统VC++程序出现“试图执行系统不支持的操作”
- 不能显示隐藏文件的问题
- pytorch---之指定GPU
- 松下伺服电机pwm控制连线_从零打造树莓派家庭监控 (一): 伺服电机控制
- linux查看都哪口状态,linux c 查看网口状态
- 连接超时_记一次网络请求连接超时的事故
- 安卓mysql类库_Android 链接mysql数据库
- html代码放进json数据,用json数据填充html表
- linux日志打印规则,Linux 打印简单日志(一)