【转载】ASP.NET MVC的过滤器
APS.NET MVC中(以下简称“MVC”)的每一个请求,都会分配给相应的控制器和对应的行为方法去处理,而在这些处理的前前后后如果想再加一些额外的逻辑处理。这时候就用到了过滤器。
MVC支持的过滤器类型有四种,分别是:Authorization(授权),Action(行为),Result(结果)和Exception(异常)。如下表,
过滤器类型 |
接口 |
描述 |
Authorization |
IAuthorizationFilter |
此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法 |
Exception |
IExceptionFilter |
用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常 |
Action |
IActionFilter |
用于进入行为之前或之后的处理 |
Result |
IResultFilter |
用于返回结果的之前或之后的处理 |
但是默认实现它们的过滤器只有三种,分别是Authorize(授权),ActionFilter,HandleError(错误处理);各种信息如下表所示
过滤器 |
类名 |
实现接口 |
描述 |
ActionFilter |
AuthorizeAttribute |
IAuthorizationFilter |
此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法 |
HandleError |
HandleErrorAttribute |
IExceptionFilter |
用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常 |
自定义 |
ActionFilterAttribute |
IActionFilter和IResultFilter |
用于进入行为之前或之后的处理或返回结果的之前或之后的处理 |
下面介绍的过滤器中,除了上面这几种外,还多加一种过滤器OutputCache
1 授权过滤器Authorize
1.1 默认Authorize使用
现在在网上无论是要求身份验证的地方多得是,发邮件,买东西,有时候就算吐个槽都要提示登录的。这里的某些操作,就是要经过验证授权才被允许。在MVC中可以利用Authorize来实现。例如一个简单的修改密码操作
[Authorize]
public ActionResult ChangePassword()
{
return View();
}
它需要用户通过了授权才能进入到这个行为方法里面,否则硬去请求那个页面的话,只会得到这个结果
如果要通过验证,通过调用FormsAuthentication.SetAuthCookie方法来获得授权,登陆的页面如下
@model FilterTest.Models.LogInModel
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<title>Login</title>
</head>
<body>
<div>
@using( Html.BeginForm()){
<div>
ID:@Html.TextBoxFor(m=>m.UserName)
<br />
Password:@Html.PasswordFor(m => m.Password)
<br />
<input type="submit" value="login" />
</div>
}
</div>
</body>
</html>
行为方法如下
[HttpPost]//这里用了谓词过滤器,只处理POST的请求
public ActionResult Login(LogInModel login)
{
if (login.UserName == "admin" && login.Password == "")
{
FormsAuthentication.SetAuthCookie(login.UserName, false);
return Redirect("/Customer/ChangePassword");
} return View();
}
当然有登录也要有注销,因为注销是在登陆之后发生的,没登陆成功也就没有注销,所以注销的行为方法也要加上Authorize过滤器,注销调用的是FormsAuthentication.SignOut方法,代码如下
[Authorize]
public ActionResult LogOut()
{
FormsAuthentication.SignOut();
return Redirect("/Customer/Login");
}
1.2 自定义授权
我们不一定要用MVC默认的Authorize授权验证规则,规则可以自己来定,自定义授权过滤器可以继承AuthorizeAttribute这个类,这个类里面有两个方法是要重写的
- bool AuthorizeCore(HttpContextBase httpContext):这里主要是授权验证的逻辑处理,返回true的则是通过授权,返回了false则不是。
- void HandleUnauthorizedRequest(AuthorizationContext filterContext):这个方法是处理授权失败的事情。
这里就定义了一个比较骑呢的授权处理器,当请求的时候刚好是偶数分钟的,就通过可以获得授权,反之则不通过。当授权失败的时候,就会跳转到登陆页面了。
public class MyAuthorizeAttribute:AuthorizeAttribute
{ protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//return base.AuthorizeCore(httpContext);
return DateTime.Now.Minute % ==
} protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.HttpContext.Response.Redirect("/Customer/Login"); //base.HandleUnauthorizedRequest(filterContext);
}
}
然后用到一个行为方法上,
[MyAuthorize]
public ActionResult ShowDetail()
{
return View();
}
每当偶数分钟的时候就可以访问得到这个ShowDetail的视图,否则就会跳到了登陆页面了。
2 处理错误过滤器HandleError
2.1 默认HandleError使用
在往常的开发中,想到异常处理的马上就会想到try/catch/finally语句块。在MVC里面,万一在行为方法里面抛出了什么异常的,而那个行为方法或者控制器有用上HandleError过滤器的,异常的信息都会在某一个视图显示出来,这个显示异常信息的视图默认是在Views/Shared/Error
这个HandleError的属性如下
属性名称 |
类型 |
描述 |
ExceptionType |
Type |
要处理的异常的类型,相当于Try/Catch语句块里Catch捕捉的类型,如果这里不填的话则表明处理所有异常 |
View |
String |
指定需要展示异常信息的视图,只需要视图名称就可以了,这个视图文件要放在Views/Shared文件夹里面 |
Master |
String |
指定要使用的母版视图的名称 |
Order |
Int |
指定过滤器被应用的顺序,默认是-1,而且优先级最高的是-1 |
这个Order属性其实不只这个HandleError过滤器有,其优先级规则跟其他过滤器的都是一样。
下面则故意弄一个会抛异常的行为方法
[HandleError(ExceptionType = typeof(Exception))]
public ActionResult ThrowErrorLogin()
{
throw new Exception("this is ThrowErrorLogin Action Throw");
}
光是这样还不够,还要到web.config文件中的<system.web>一节中添加以下代码
<customErrors mode="On" />
因为默认的开发模式中它是关闭的,要等到部署到服务器上面才会开启,让异常信息比较友好的用一个视图展现。
像这里访问ThrowErrorLogin视图时,由于抛出了一次,就转到了一个特定的视图
在这里看到的异常视图是这样的,除了用这个建项目时默认生成的异常视图之外,我们还可以自己定义异常视图,视图里面要用到的异常信息,可以通过@Model获取,它是一个ExceptionInfo类型的实例,例如这里建了一个异常视图如下
@{
Layout = null;
} <!DOCTYPE html> <html>
<head>
<title>MyErrorPage</title>
</head>
<body>
<div>
<p>
There was a <b>@Model.Exception.GetType().Name</b>
while rendering <b>@Model.ControllerName</b>'s
<b>@Model.ActionName</b> action.
</p>
<p style="color:Red">
<b>@Model.Exception.Message</b>
</p>
<p>Stack trace:</p>
<pre style=" background-color:Orange">@Model.Exception.StackTrace</pre>
</div>
</body>
</html>
它存放的路径是~/Views/Shared里面,像上面的行为方法如果要用异常信息渲染到这个视图上面,在控制器的处改成这样就可以了
[HandleError(ExceptionType = typeof(Exception), View = "MyErrorPage")]
2.2 自定义错误异常处理
这里的错误处理过滤器也可以自己来定义,做法是继承HandleErrorAttribute类,重写void OnException(ExceptionContext filterContext)方法,这个方法调用是为了处理未处理的异常,例如
public override void OnException(ExceptionContext filterContext)
{
//base.OnException(filterContext);
if (!filterContext.ExceptionHandled &&
filterContext.Exception.Message == "this is ThrowErrorLogin Action Throw")
{
filterContext.ExceptionHandled=true;
filterContext.HttpContext.Response.Write("5洗ten No Problem<br/>" +
filterContext.Exception.ToString());
}
}
这里用到的传入了一个ExceptionContext的对象,既可以从它那里获得请求的信息,又可以获取异常的信息,它部分属性如下
属性名称 | 类型 | 描述 |
ActionDescriptor | ActionDescriptor | 提供详细的操作方法 |
Result | ActionResult | 结果的操作方法,过滤器可以取消,要求将此属性设置为一个非空值 |
Exception | Exception | 未处理的异常 |
ExceptionHandled | bool | 另一个过滤器,则返回true,如果有明显的异常处理 |
这里的ExceptionHandler属性要提一下的是,如果这个异常处理完的话,就把它设为true,那么即使有其他的错误处理器捕获到这个异常,也可以通过ExceptionHandler属性判断这个异常是否经过了处理,以免重复处理一个异常错误而引发新的问题。
3 OutputCache过滤器
OutputCache过滤器用作缓存,节省用户访问应用程序的时间和资源,以提高用户体验,可这个我试验试不出它的效果。留作笔记记录一下。OutputCacheAttribute这个类有以下属性
属性名称 |
类型 |
描述 |
Duration |
int |
缓存的时间,以秒为单位,理论上缓存时间可以很长,但实际上当系统资源紧张时,缓存空间还是会被系统收回。 |
VaryByParam |
string |
以哪个字段为标识来缓存数据,比如当“ID”字段变化时,需要改变缓存(仍可保留原来的缓存),那么应该设VaryByParam为"ID"。这里你可以设置以下几个值: |
Location |
OutputCacheLocation |
缓存数据放在何处。默认是Any,其他值分别是Client,Downstream,Server,None,ServerAndClient |
NoStore |
bool |
用于决定是否阻止敏感信息的二级存储。 |
例如一个OutputCache过滤器可以这样使用
[OutputCache(Location= System.Web.UI.OutputCacheLocation.Client,Duration=)]
public ActionResult Login()
{
return View();
}
或者有另外一种使用方式——使用配置文件,在<system.web>节点下添加以下设置
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="testCache" location="Client" duration="60"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
使用控制的时候就这样
[OutputCache(CacheProfile="testCache")]
public ActionResult Login()
{
return View();
}
4 自定义过滤器
万一前面介绍的过滤器也满足不了需求,要在行为方法执行返回的前前后后定义自己的处理逻辑的话,这个自定义过滤器就应该能派上用场了。若要自定义一个过滤器,则要继承ActionFilterAttribute类,这个类是一个抽象类,实现了IActionFilter和IResultFilter接口,主要通过重写四个虚方法来达到在行为方法执行和返回的前后注入逻辑
方法 |
参数 |
描述 |
OnActionExecuting |
ActionExecutingContext |
在行为方法执行前执行 |
OnActionExecuted |
ActionExecutedContext |
在行为方法执行后执行 |
OnResultExecuting |
ResultExecutingContext |
在行为方法返回前执行 |
OnResultExecuted |
ResultExecutedContext |
在行为方法返回后执行 |
四个方法执行顺序是OnActionExecuting——>OnActionExecuted——>OnResultExecuting——>OnResultExecuted。上面四个方法的参数都是继承基ContollorContext类。例如下面定义了一个自定义的过滤器
public class MyCustomerFilterAttribute : ActionFilterAttribute
{
public string Message { get; set; } public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
filterContext.HttpContext.Response.Write(string.Format( "<br/> {0} Action finish Execute.....",Message));
} public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CheckMessage(filterContext);
filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action start Execute.....", Message));
base.OnActionExecuting(filterContext);
} public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action finish Result.....", Message));
base.OnResultExecuted(filterContext);
} public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write(string.Format("<br/> {0} Action start Execute.....", Message));
base.OnResultExecuting(filterContext);
} private void CheckMessage(ActionExecutingContext filterContext)
{
if(string.IsNullOrEmpty( Message)||string.IsNullOrWhiteSpace(Message))
Message = filterContext.Controller.GetType().Name + "'s " + filterContext.ActionDescriptor.ActionName;
}
}
使用它的行为方法定义如下
[MyCustomerFilter]
public ActionResult CustomerFilterTest()
{
Response.Write("<br/>Invking CustomerFilterTest Action");
return View();
}
执行结果如下
这个就证明了上面说的顺序。
当控制器也使用上这过滤器时,而行为方法不使用时,结果如下
如果控制器和行为方法都使用了过滤器,理论上是显示上面两个结果的有机结合。但实际不然,因为在定义过滤器的时候还少了一个特性:[AttributeUsage(AttributeTargets.All, AllowMultiple = true)],把这个加在MyCustomerFilterAttribute就行了。
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]//多次调用
public class MyCustomerFilterAttribute : ActionFilterAttribute
{
……
}
由这幅图可以看出,同一个过滤器分别用在了控制器和行为方法中,执行同一个方法时都会有先后顺序,如果按默认值(不设Order的情况下),一般的顺序是由最外层到最里层,就是“全局”——>“控制器”——>“行为方法”;而特别的就是错误处理的过滤器,由于异常是由里往外抛的,所以它的顺序刚好也反过来:“行为方法”——>“控制器”——>“全局”。
既然这里有提到全局的过滤器,那么全局的过滤器是在Global.asax文件里面的RegisterGlobalFilters(GlobalFilterCollection filters)中设置的
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new MyFilters.MyCustomerFilterAttribute() { Message="Global"});//全局过滤器
}
这里它默认也添加了一个错误处理的过滤器来处理整个MVC应用程序所抛出的异常。
好了,过滤器介绍到此结束了。最后附上了源码,整理的不算很好,有什么不足的错的恳请大家多多指点,谢谢!
转自:http://www.cnblogs.com/HopeGi/p/3342083.html
【转载】ASP.NET MVC的过滤器的更多相关文章
- 转载 ASP.NET MVC中使用ASP.NET Identity
转载原地址: http://blog.jobbole.com/90695/ 在之前的文章中,我为大家介绍了OWIN和Katana,有了对它们的基本了解后,才能更好的去学习ASP.NET Identit ...
- 使用ASP.NET MVC操作过滤器记录日志(转)
使用ASP.NET MVC操作过滤器记录日志 原文地址:http://www.singingeels.com/Articles/Logging_with_ASPNET_MVC_Action_Filte ...
- ASP.NET MVC : Action过滤器(Filtering)
http://www.cnblogs.com/QLeelulu/archive/2008/03/21/1117092.html ASP.NET MVC : Action过滤器(Filtering) 相 ...
- [翻译] 使用ASP.NET MVC操作过滤器记录日志
[翻译] 使用ASP.NET MVC操作过滤器记录日志 原文地址:http://www.singingeels.com/Articles/Logging_with_ASPNET_MVC_Action_ ...
- ASP.NET MVC动作过滤器
ASP.NET MVC提供了4种不同的动作过滤器(Aciton Filter). 1.Authorization Filter 在执行任何Filter或Action之前被执行,用于身份验证 2.Act ...
- Asp.net MVC 之过滤器
整理一下MVC中的几种过滤器,以及每种过滤器是干什么用的 四种过滤器 1.AuthorizationFilter(授权过滤器) 2.ActionFilter(方法过滤器) 3.ResultFilter ...
- 转载ASP.NET MVC 和ASP.NET Web Form简单区别
转载原地址 http://www.cnblogs.com/lei2007/p/3315431.html 概论: Asp.net 微软 提供web开发框架或者技术.分Web Form和ASP.NET ...
- Asp.net MVC 权限过滤器实现方法的最佳实践
在项目开发中,为了安全.方便地判断用户是否有访问当前资源(Action)的权限,我们一般通过全局过滤器来实现. Asp.net MVC 页面中常见的权限判断使用过滤器主要在以下几种情况(根据权限判断的 ...
- ASP.NET MVC 系统过滤器、自定义过滤器
一.系统过滤器使用说明 1.OutputCache过滤器 OutputCache过滤器用于缓存你查询结果,这样可以提高用户体验,也可以减少查询次数.它有以下属性: Duration:缓存的时间,以秒为 ...
- Asp.Net MVC在过滤器中使用模型绑定
废话不多话,直接上代码 1.创建MVC项目,新建一个过滤器类以及使用到的实体类: public class DemoFiltersAttribute : AuthorizeAttribute { pu ...
随机推荐
- YprogressBar,html5进度条样式,js进度条插件
简介 YprogressBar是一款基于HTML5的进度条插件. YprogressBar是一款轻量级进度条插件,使用方便,资源占用少,模仿好压的解压界面,带有数字显示,同时支持在描述中增加参数,以动 ...
- make file教程(转)
最近在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了以下这篇文章.通俗易懂.然后把它贴出 ...
- ssl小结
有几篇不错的文章: http://www.cnblogs.com/pen-ink/archive/2011/01/17/1937680.html 这个应该是最简单的示例了. 不过,当两个passwor ...
- WebViewJavascriptBridge的暂时理解
直接从项目里复制了一份关于WebViewJavascriptBridge使用的代码,注释部分是自己暂时的理解.孟哥说,callHandler类似于jq里的trigger, registerHandle ...
- DDD~领域层
回到目录 再论Domain与Infrastructure 在面向领域的设计中,领域层(Domain)实现上是位于最底层的,其它层有对它的引用,包括基础设施层(Infrastructure)也是去引用领 ...
- 使用finfo_file()函数检测上传图片的类型
该函数可以检测文件的MIME类型.因为有时候我们只根据文件后缀来判断是不准确的. function getMIME($filename){ $finfo = finfo_open(FILEINFO_M ...
- Excel快速改变行列的次序
改变行列次序是在Excel中常常需要进行的操作,多数用户的方法是先剪切要调整的行或列,然后选定目标位置,单击菜单“插入”→“剪切单元格”. 事实上,使用键盘来配合的话,改变行列的次序可以更快捷.比 ...
- salesforce 零基础学习(二十七)VF页面等待(loading)效果制作
进行查询的情况下,显示友好的等待效果可以让用户更好的了解目前的状态以及减少用户消极的等待,例如下图所示. VF提供了<apex:actionStatus>标签,,此标签用于显示一个AJAX ...
- SQLServer查看死锁
SQLServer查看死锁 if exists ( select * from sys.procedures where name like '%USP_ShowLocks%' ) drop proc ...
- vuejs件同一个挂载点上切换组
vuejs件同一个挂载点上切换组 动态组件 http://cn.vuejs.org/guide/components.html#动态组件 多个组件可以使用同一个挂载点,然后动态地在它们之间切换.使用保 ...