MVC4过滤器(转)
先来看看一个例子演示过滤器有什么用:
public class AdminController : Controller {
// ... instance variables and constructor
public ViewResult Index() {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
// ...rest of action method
}
public ViewResult Create() {
if (!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
// ...rest of action method
}
...
AdminController控制器的众多Action中我们都需要判定当前验证用户,这里有很多重复的代码,我们可以简化为:
[Authorize]
public class AdminController : Controller {
// ... instance variables and constructor
public ViewResult Index() {
// ...rest of action method
}
public ViewResult Create() {
// ...rest of action method
}
...
Authorize特性类AuthorizeAttribute就称作MVC的Filter,它在横向为MVC框架扩展功能,让我们可以更方便的处理日志、授权、缓存等而不影响纵向主体功能。
MVC常用的滤器类型:
- Authorization:实现IAuthorizationFilter接口,默认实现类AuthorizeAttribute,在调用Action方法前首先处理认证信息。
- Action:实现IActionFilter接口,默认实现类ActionFilterAttribute,在运行Action前后调用实现一些额外的动作。
- Result:实现IResultFilter接口,默认实现类ActionFilterAttribute,在action result运行前后调用实现额外的动作。
- Exception:实现IExceptionFilter接口,默认实现类HandleErrorAttribute,仅在其他过滤器或者action方法或者action result抛出异常时调用。
过滤器可以应用在整个控制器类上,也可以单对某个Action方法,当然也可以是同时应用多个过滤器:
[Authorize(Roles="trader")] // applies to all actions
public class ExampleController : Controller {
[ShowMessage] // applies to just this action
[OutputCache(Duration=)] // applies to just this action
public ActionResult Index() {
// ... action method body
}
}
Authorization过滤器
Authorization过滤器用于控制仅授权的用户可以调用某个Action方法,它必须实现IAuthorizationFilter接口:
namespace System.Web.Mvc {
public interface IAuthorizationFilter {
void OnAuthorization(AuthorizationContext filterContext);
}
}
处理安全方面的代码必须谨慎全面,一般我们不要直接实现接口IAuthorizationFilter,而从AuthorizeAttribute扩展自定义类:
public class CustomAuthAttribute : AuthorizeAttribute {
private bool localAllowed;
public CustomAuthAttribute(bool allowedParam) {
localAllowed = allowedParam;
}
protected override bool AuthorizeCore(HttpContextBase httpContext) {
if (httpContext.Request.IsLocal) {
return localAllowed;
} else {
return true;
}
}
}
这里定义了CustomAuthAttribute过滤器,如果请求来自于非本机总是允许,如果是本机请求则视传入参数allowedParam而定:
public class HomeController : Controller {
[CustomAuth(false)]
public string Index() {
return "This is the Index action on the Home controller";
}
}
默认实现AuthorizeAttribute足够应付多数授权功能限制,我们可以传入参数限制访问的用户或者角色:
[Authorize(Users = "adam, steve, jacqui", Roles = "admin")]
需要注意的是AuthorizeAttribute仅仅负责授权,而用户的认证则依赖于ASP.NET的认证机制。
Exception过滤器
Exception过滤器需要实现IExceptionFilter接口:
namespace System.Web.Mvc {
public interface IExceptionFilter {
void OnException(ExceptionContext filterContext);
}
}
从filterContext我们可以获取很多相关信息,比如Controller、HttpContext、IsChildAction、RouteData、Result、Exception、ExceptionHandled等。异常的具体信息我们可以从Exception获取,我们设置ExceptionHandled为true报告异常已经处理,在设置为true之前最好检查异常是否已经被action方法上其他的过滤器处理,以避免重复的错误纠正动作。如果异常未被处理(ExceptionHandled!=true),MVC框架使用默认的异常处理程序显示ASP.NET的黄屏错误页面。
我们可以创建自定义的异常过滤器:
public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter {
public void OnException(ExceptionContext filterContext) {
if (!filterContext.ExceptionHandled &&
filterContext.Exception is ArgumentOutOfRangeException) {
int val = (int)(((ArgumentOutOfRangeException)filterContext.Exception).ActualValue);
//filterContext.Result = new RedirectResult("~/Content/RangeErrorPage.html");
filterContext.Result = new ViewResult {
ViewName = "RangeError",
ViewData = new ViewDataDictionary<int>(val)
};
filterContext.ExceptionHandled = true;
}
}
}
注意这里RangeExceptionAttribute除了实现IExceptionFilter接口还从FilterAttribute继承,这是因为MVC的过滤器类还必须实现IMvcFilter接口,这里我们没有直接实现IMvcFilter接口,改为从默认封装类FilterAttribute继承。如下使用这个自定义过滤器:
[RangeException]
public string RangeTest(int id) {
if (id > ) {
return String.Format("The id value is: {0}", id);
} else {
throw new ArgumentOutOfRangeException("id");
}
}
在发生异常时过滤器会将我们重定向到RangeError视图。
通常我们不需要创建自己的异常处理器,而使用MVC提供的默认过滤器HandleErrorAttribute:
[HandleError(ExceptionType = typeof(ArgumentOutOfRangeException), View = "RangeError",Master="")]
属性ExceptionType指定要处理的异常类型,如果不指定则处理所有异常类型;view指定错误时要渲染的视;master指定所用的页面布局。
在使用HandleErrorAttribute过滤前我们必须在Web.config的<System.Web>一节启用CusomErrors:
<customErrors mode="On" defaultRedirect="/Content/RangeErrorPage.html"/>
默认customErros为RemoteOnly,defaultRedirect指定一个默认的错误页面。
Action过滤器
Action过滤器必须实现IActionFilter接口:
namespace System.Web.Mvc {
public interface IActionFilter {
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActionExecutedContext filterContext);
}
}
OnActionExecuting()在调用action方法前调用,OnActionExecuted()则在调用action方法后调用。
OnActionExecuting的一个实现例子:

public class CustomActionAttribute : FilterAttribute, IActionFilter {
public void OnActionExecuting(ActionExecutingContext filterContext) {
if (filterContext.HttpContext.Request.IsLocal) {
filterContext.Result = new HttpNotFoundResult();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
// not yet implemented
}
}

这里我们仅实现了OnActionExecuting方法,在从本地请求任何应用此过滤器的action方法时返回404错误。
OnActionExecuted的一个例子:

public class ProfileActionAttribute : FilterAttribute, IActionFilter {
private Stopwatch timer;
public void OnActionExecuting(ActionExecutingContext filterContext) {
timer = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
timer.Stop();
if (filterContext.Exception == null) {
filterContext.HttpContext.Response.Write(
string.Format("<div>profile result method elapsed time: {0}</div>",
timer.Elapsed.TotalSeconds));
}
}
}

在调用action方法前我们启动计时器,在action方法调用后停止计时器并输出计时器所计action方法运行时长。
Result过滤器
Result过滤器实现IResultFilter接口:
namespace System.Web.Mvc {
public interface IResultFilter {
void OnResultExecuting(ResultExecutingContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
}
}
Result过滤器操作的是action方法返回结果,有意思的是即使action方法返回void所应用的Result过滤器也会动作。
类似上面的ProfileAction过滤器我们可以对Result运行计时:

public class ProfileResultAttribute : FilterAttribute, IResultFilter {
private Stopwatch timer;
public void OnResultExecuting(ResultExecutingContext filterContext) {
timer = Stopwatch.StartNew();
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
timer.Stop();
filterContext.HttpContext.Response.Write(
string.Format("<div>Result elapsed time: {0}</div>",
timer.Elapsed.TotalSeconds));
}
}

内建的Result过滤器类ActionFilterAttribute
MVC为我们提供了ActionFilterAttribute类,它同时实现了action和result过滤器接口:

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) {
}
}
}

我们只需要继承该类并重载需要的方法,比如:

public class ProfileAllAttribute : ActionFilterAttribute {
private Stopwatch timer;
public override void OnActionExecuting(ActionExecutingContext filterContext) {
timer = Stopwatch.StartNew();
}
public override void OnResultExecuted(ResultExecutedContext filterContext) {
timer.Stop();
filterContext.HttpContext.Response.Write(
string.Format("<div>Total elapsed time: {0}</div>",
timer.Elapsed.TotalSeconds));
}
}

Controller类的过滤器支持
MVC的Controller类内部实现了IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilte四个接口,并提供OnXXX的虚函数供调用,比如:
public class HomeController : Controller {
private Stopwatch timer;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
timer = Stopwatch.StartNew();
}
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
timer.Stop();
filterContext.HttpContext.Response.Write(
string.Format("<div>Total elapsed time: {0}</div>",
timer.Elapsed.TotalSeconds));
}
全局过滤器
全局过滤器应用于应用程序内所有控制器的所有action方法,我们在App_Start/FilterConfig.cs可以注册全局过滤器:
public class FilterConfig {
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
filters.Add(new HandleErrorAttribute());
filters.Add(new ProfileAllAttribute());
}
}
HandleErrorAttribute是VS为我们默认添加的,用于未处理异常错误时显示/Views/Shared/Error.cshtml页面;ProfileAllAttribute则是我们添加的自定义过滤器,运行任何action方法时都会调用这个过滤器。
其他MVC内建过滤器
MVC框架还内建提供以下过滤器:
- RequireHttps:指示必须以HTTPS访问action方法,仅用于HTTP get方法
- OutputCache:缓存action方法的结果
- ValidateInput和ValidationAntiForgeryToken:安全授权相关的过滤器
- AsnycTimeOut和NoAsyncTimeout:用于异步控制器
- ChildActionOnlyAttribute:用于授权Html.Action或者Html.RenderAction调用子action方法
这些过滤器的使用方法可以参见MSDN。
过滤器的运行顺序
过滤器的运行按先后顺序是:authorization过滤器、action过滤器、result过滤器,期间任何时刻发生未处理异常调用异常处理器。这是针对不同类型的过滤器,但是如果所应用的是同一类的过滤器呢?MVC默认并不保证同类型过滤器的调用程序,也就是说很可能并非按照出现在代码中的先后程序来调用过滤器,但是我们可以显式的指定它们的调用顺序:

...
[SimpleMessage(Message="A", Order=2)]
[SimpleMessage(Message="B", Order=1)]
public ActionResult Index() {
Response.Write("Action method is running");
return View();
}
...

这里SimpleMessage是一个action过滤器,通过order我们指定它们的运行顺序: B->OnActionExecuting、A->OnActionExecuting、A->OnActionExecuted、B->OnActionExecuted。注意A的OnActionExecuted先于B的OnActionExecuted,和OnActionExecuting正好相反,这是无法改变的。在不指定order时,MVC内部指定为-1。另外如果同类型过滤器指定相同的order比如都是1,还要根据在哪里应用的过滤器来分先后执行:首先执行的是全局过滤器、然后是控制器类上、最后才是action方法;例外的是exception过滤器,它的顺序正好与此相反!
更多:
MVC4过滤器(转)的更多相关文章
- asp.net mvc4 过滤器的简单应用:登录验证
直接上代码,不要说话. ASP.NET MVC4过滤器的简单应用:验证登录 [AcceptVerbs(HttpVerbs.Post)] public ActionResult login(FormCo ...
- MVC4过滤器
MVC4提供的四种基本类型过滤器接口,IAuthorizationFilter.IActionFilter.IResultFilter和IExceptionFilter,可通过继承对应的接口和Filt ...
- MVC4 过滤器(转)
先来看看一个例子演示过滤器有什么用: public class AdminController : Controller { // ... instance variables and constru ...
- MVC4 过滤器使用和怎样控制全部action和部分action
MVC中的过滤器分四种分别为:IActionFilter(动作过滤器), IAuthorizationFilter(授权过滤器), IExceptionFilter(异常过滤器), IResultFi ...
- Asp.Net Mvc Action过滤器(二)
在Mvc中为Action添加过滤器,有两种方式, 一.使用ActionFilterAttribute,简单方式,同时支持Result的过滤处理, 1.可以为空,支持的重写:OnActionExecut ...
- Action过滤器使用实例(一)
1.实例一 /// <summary> /// 需要用户登陆的 action,执行提前验证 /// </summary> public class LoginFilterAtt ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-[过滤器+Cache] 系列目录 上次的探讨没有任何结果,我浏览了大量的文章 ...
- Asp.Net MVC4中的全局过滤器,
可以对整个项目进行全局监控. 新建一个MVC4项目,可以在global.asax文件中看到如下代码: FilterConfig.RegisterGlobalFilters(GlobalFilters ...
- C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用
C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备) https://blog.csdn.net/u013519551/article/details/51220841 1. . ...
随机推荐
- C# 解析嵌套的json文件.
概述 今天我同学问我如何转换json文件,没处理过,网上搜了一下,json转excel的很少,反过来倒是有许多人写了工具. json文件的结构大致是这样的: {, , }, , "type& ...
- 报错: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is ins
环境:Xcode7.1.1 + iOS9.1 详细错误: App Transport Security has blocked a cleartext HTTP (http://) resource ...
- Cookie[1]
1.什么是Cookie Cookie是一小段文本类型的数据,由服务器发送,并保留在客户端的计算机上. 2.Cookie的作用 服务器可以利用Cookie包含的信息来筛选并经常维护这些信息,以判断在Ht ...
- 获取GET/POST提交的数据,并处理中文问题
1.获取input标签中的值,用request.getParameter("User")(User为input的name值) 2. 获取checkbox的值,由于是多选的,所以不能 ...
- C++,关于类和结构体中,成员访问属性(public,private)
今天发现一个的问题: #include <vector> #include <iostream> #include <algorithm> #include < ...
- php时间戳与时间转换
PHP时间大的来分有两种,一是时间戳类型(1228348800),二是正常日期格式(2008-12-4) 所以存到数据库也有两种形式了(真正不止,我的应用就两种),时间戳类型我是保存为字符串的,这个是 ...
- 使用HTML5中的Canves标签制作时钟特效
<!DOCTYPE html > <html> <head> </head> <body> <canvas id="cloc ...
- ECSTORE2.0 下载 (变量标签)
条目 用途 备注 coupon.mc.use_times 优惠券可用次数 - security.guest.enabled 是否支持非会员购物 - site.version version的最后修改时 ...
- C#关于等待窗体(转)
c#.net 中如果想在主窗口A里点击打开新窗口B(因为要数据库操作,Bload需一小段时间)之前弹出带有滚动条等待子窗口C来提示用户没有死机,应该怎么做?我用多线程打开了c窗口,但是问题:1.C窗口 ...
- 作为一个新人,怎样学习嵌入式Linux,(韦东山)
很早以前在网上看到的韦东山老师写的文章,复制到自己的博客,方便自己以后看. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学到什 ...