本文参考:http://www.cnblogs.com/willick/p/3331520.html

1、Filter(过滤器)是基于AOP(Aspect-Oriented Programming 面向切面编程)的设计。作用是对MVC框架处理客户端请求注入额外的逻辑,以非常优美简单的方式实现横切关注点(Cross-cutting Concerns)。所谓横切关注点是指横越应用程序多个甚至所有模块的功能,经典的横切关注点有日志记录、缓存处理、异常处理和权限验证等。

2、MVC框架支持的Filter可以分为四类,每一个类都可以在处理请求的不同时间点注入额外的逻辑处理。这四类Filter如下图:

其中ActionFilter是一个抽象类,使用之前必须对它进行实现;而另外两个则有默认实现可以直接调用。这些Filter既可以用在单个Action上,也可以用在整个Controller上。

   对于自定义的Controller基类,应用于该基类的Filter也将对继承自该基类的子类有效。

2、Authorization Filter是在Action和其他种类的Filter之前运行的,作用是强制实施权限策略,保证Action只被授权了的用户调用。它实现的接口如下:

namespace System.Web.Mvc
{
public interface IAuthorizationFilter
{
void OnAuthorization(AuthorizationContext filterContext);
}
}

我们可以通过继承IAuthorizationFilter接口自定义Authorization Filter。下列示例自定义了一个Filter用于验证是否允许本地请求。

//AuthorizeAttribte 类帮我们内置地实现了很多东西,我们只需把重点放在 AuthorizeCore 方法上,在该方法中实现权限认证的逻辑。
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;
}
}
}
[Authorize(Users = "jim, steve, jack", Roles = "admin")]//使用内置的Authorization Filter,该语句的意思是只允许角色为admin、且用户名必须是jim、steve、jack中的一个的用户访问该Action
public string Index()
{
return "This is the Index action on the Home controller";
}

3、Exception Filter在下面三种来源抛出未处理异常时运行:

  • 另外一种Filter(如Authorization、Action或Result等Filter)。
  • Action方法本身。
  • Action方法执行完成(即处理ActionResult的时候)。

Exception Filter 必须实现接口IExceptionFilter,该接口定义为:

namespace System.Web.Mvc
{
public interface IExceptionFilter
{
void OnException(ExceptionContext filterContext);
}
}

ExceptionContext继承自ControllerContext,后者的常用属性说明:

  • Controller,返回当前请求的controller对象。
  • HttpContext,提供请求和响应的详细信息。
  • IsChildAction,如果是子action则返回true(稍后将简单介绍子action)。
  • RequestContext,提供请求上下文信息。
  • RouteData,当前请求的路由实例信息。

ExceptionContext的常用属性说明:

  • ActionDescriptor,提供action方法的详细信息。
  • Result,是一个 ActionResult 类型,通过把这个属性值设为非空可以让某个Filter的执行取消。
  • Exception,未处理异常信息。
  • ExceptionHandled,如果另外一个Filter把这个异常标记为已处理则返回true。

一个Exception Filter可以通过把 ExceptionHandled 属性设置为true来标注该异常已被处理过,这个属性一般在某个action方法上应用了多个Exception Filter时会用到。ExceptionHandled 属性设置为true后,就可以通过该属性的值来判断其它应用在同一个action方法上的Exception Filter是否已经处理了这个异常,以免同一个异常在不同的Filter中重复被处理。示例:

//1、Filter的定义,通过重定向到Content目录下的一个静态html文件来显示友好的 ArgumentOutOfRangeException 异常信息。
//RangeExceptionAttribute 类继承了FilterAttribute类,并且实现了IException接口。
//作为一个MVC Filter,它的类必须实现IMvcFilter接口,你可以直接实现这个接口,但更简单的方法是继承 FilterAttribute 基类
public class RangeExceptionAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled && filterContext.Exception is ArgumentOutOfRangeException)
{
filterContext.Result = new RedirectResult("~/Content/RangeErrorPage.html");
filterContext.ExceptionHandled = true;
}
}
} //2、RangeErrorPage.html页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Range Error</title>
</head>
<body>
<h2>Sorry</h2>
<span>One of the arguments was out of the expected range.</span>
</body>
</html> //3、HomeController中添加一个值越限时抛出异常的action
public class HomeController : Controller
{
[RangeException]
public string RangeTest(int id)
{
if (id > )
{
return String.Format("The id value is: {0}", id);
}
else
{
throw new ArgumentOutOfRangeException("id", id, "");
}
}
}

由于静态的html文件是和后台脱离的,所以实际项目中更多的是用一个View来呈现友好的错误信息,以便很好的对它进行一些动态的控制:

//1、定义Filter
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 ViewResult
{
ViewName = "RangeError",
ViewData = new ViewDataDictionary<int>(val)
};
filterContext.ExceptionHandled = true;
}
}
} //2、RangeError.cshtml
@model int <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Range Error</title>
</head>
<body>
<h2>Sorry</h2>
<span>The value @Model was out of the expected range.</span>
<div>
@Html.ActionLink("Change value and try again", "Index")
</div>
</body>
</html>

4、程序发布后不应该显示异常信息给用户看。我们可以通过配置Web.config让应用程序不管在何时何地引发了异常(即使是在View中的异常)都可以显示统一的友好错误信息。在Web.config文件中的<system.web>节点下添加如下子节点:

<system.web><customErrors mode="On" defaultRedirect="/Content/RangeErrorPage.html"/>//这个配置只对远程访问有效,本地运行站点依然会显示跟踪信息。
</system.web>

5、MVC框架内置的 HandleErrorAttribute包含ExceptionType、View和Master三个属性。当ExceptionType属性指定类型的异常被引发时,这个Filter将用View属性指定的View(使用默认的Layout或Mast属性指定的Layout)来呈现一个页面。示例:

[HandleError(ExceptionType = typeof(ArgumentOutOfRangeException), View = "RangeError")]
public string RangeTest(int id)
{
if (id > )
{
return String.Format("The id value is: {0}", id);
} else
{
throw new ArgumentOutOfRangeException("id", id, "");
}
}

使用内置的HandleErrorAttribute,将异常信息呈现到View时,这个特性同时会传递一个HandleErrorInfo对象作为View的model。HandleErrorInfo类包含ActionName、ControllerName和Exception属性,如下面的 RangeError.cshtml 使用这个model来呈现信息:

@model HandleErrorInfo
@{
ViewBag.Title = "Sorry, there was a problem!";
} <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Range Error</title>
</head>
<body>
<h2>Sorry</h2>
<span>The value @(((ArgumentOutOfRangeException)Model.Exception).ActualValue)
was out of the expected range.</span>
<div>
@Html.ActionLink("Change value and try again", "Index")
</div>
<div style="display: none">
@Model.Exception.StackTrace
</div>
</body>
</html>

6、ActionFilter是对Action方法的执行进行筛选的,包括执行前和执行后。它实现了以下接口:

namespace System.Web.Mvc
{
public interface IActionFilter
{
//在action方法执行之前被调用
void OnActionExecuting(ActionExecutingContext filterContext); //在action方法执行之后被调用
void OnActionExecuted(ActionExecutedContext filterContext);
}
}

下列示例自定义了一个ActionFilter:

//自定义ActionFilter
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>Action method elapsed time: {0}</div>", timer.Elapsed.TotalSeconds));
}
}
} //在HomeController中添加一个Action并应用该Filter
[ProfileAction]
public string FilterTest()
{
return "This is the ActionFilterTest action";
}

7、Result Filter用来处理action方法返回的结果,是在Action Filter之后执行的。用法和Action Filter类似,它需要实现 IResultFilter 接口,定义如下:

namespace System.Web.Mvc
{
public interface IResultFilter
{
void OnResultExecuting(ResultExecutingContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
}
}

示例代码:

//1、Filter 定义
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));
}
} //2、应用
[ProfileAction]
[ProfileResult]
public string FilterTest()
{
return "This is the ActionFilterTest action";
}

8、MVC框架内置了一个 ActionFilterAttribute 类用来创建action 和 result 筛选器,即可以控制action方法的执行也可以控制处理action方法返回结果。它是一个抽象类,定义如下:

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

使用这个抽象类方便之处是你只需要实现需要加以处理的方法。示例:

//1、定义
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));
}
} //2、应用
[ProfileAction]
[ProfileResult]
[ProfileAll]
public string FilterTest()
{
return "This is the FilterTest action";
}

我们也可以Controller中直接重写 ActionFilterAttribute 抽象类中定义的四个方法,效果和使用Filter是一样的,例如:

public class HomeController : Controller
{
private Stopwatch timer;
...
public string FilterTest()
{
return "This is the FilterTest action";
} 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));
}
}

9、全局Filter对整个应用程序的所有controller下的所有action方法有效。在App_Start/FilterConfig.cs文件中的RegisterGlobalFilters方法,可以把一个Filter类注册为全局,如:

public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new ProfileAllAttribute()); //如此,ProfileAllAttribute将对所有的action有效
}
}

10、MVC框架内置了很多Filter,常见的有RequireHttps、OutputCache、AsyncTimeout等等。下面是几个常用的:

  • RequireHttps,强制使用HTTPS协议访问。它将浏览器的请求重定向到相同的controller和action,并加上 https:// 前缀。
  • OutputCache,将action方法的输出内容进行缓存。
  • AsyncTimeout/NoAsyncTimeout,用于异步Controller的超时设置。
  • ChildActionOnlyAttribute,使用action方法仅能被Html.Action和Html.RenderAction方法访问。

【ASP.NET MVC 学习笔记】- 12 Filter的更多相关文章

  1. ASP.NET MVC学习笔记-----Filter

    ASP.NET MVC学习笔记-----Filter(1) Filter类型 接口 MVC的默认实现 Description Authorization IAuthorizationFilter Au ...

  2. ASP.NET MVC学习笔记-----Filter(2)

    接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用,它需要实现IActionFilter接口: public ...

  3. ASP.NET MVC学习笔记-----Filter2

    ASP.NET MVC学习笔记-----Filter(2) 接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用 ...

  4. Spring MVC 学习笔记12 —— SpringMVC+Hibernate开发(1)依赖包搭建

    Spring MVC 学习笔记12 -- SpringMVC+Hibernate开发(1)依赖包搭建 用Hibernate帮助建立SpringMVC与数据库之间的联系,通过配置DAO层,Service ...

  5. ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现

    ASP.NET MVC 学习笔记-2.Razor语法   1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...

  6. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  7. ASP.NET MVC5学习笔记之Filter基本介绍

    Filter是ASP.NET MVC框架提供的基于AOP(面向方面)设计,提供在Action执行前后做一些非业务逻辑通用处理,如用户验证,缓存等.现在来看看Filter相关的一些类型信息. 一.基本类 ...

  8. ASP.NET MVC学习笔记-----Filter(1)

    Filter类型 接口 MVC的默认实现 Description Authorization IAuthorizationFilter AuthorizeAttribute 最先执行,在其他类型的fi ...

  9. ASP.NET MVC5学习笔记之Filter提供体系

    前面我们介绍了Filter的基本使用,但各种Filter要在合适的时机运行起来,需要预先准备好,现在看看ASP.NET MVC框架是怎么做的. 一.Filter集合 在ControlerActionI ...

随机推荐

  1. 201521123060 《Java程序设计》第13周学习总结

    1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2.书面作业 1.网络基础 1.1比较ping www.baidu.com与ping cec.jmu.edu ...

  2. 201521123078 《Java程序设计》第十三周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 查询Ip地址 ...

  3. chrome保存网页为单个文件(mht格式)

    网页归档(英语:MIME HTML或MIME Encapsulation of Aggregate HTML Documents,又称单一文件网页或网页封存盘案)为以多用途互联网邮件扩展格式,将一个多 ...

  4. linux crontab详解

    服务的启动和停止 cron服务是linux的内置服务,但它不会开机自动启动.可以用以下命令启动和停止服务: /sbin/service crond start /sbin/service crond ...

  5. 定位页面元素之xpath详解以及定位不到测试元素的常见问题

    一.定位元素的方法 id:首选的识别属性,W3C标准推荐为页面每一个元素设置一个独一无二的ID属性, 如果没有且很难找到唯一属性,解决方法:(1)找开发把id或者name加上.如果不行,解决思路可以是 ...

  6. 关于APP分享到QQ、微信等

    <script> var shares=null;        var Intent=null,File=null,Uri=null,main=null; function plusRe ...

  7. 极化码之tal-vardy算法(2)

    上一节我们了解了tal-vardy算法的大致原理,对所要研究的二元输入无记忆对称信道进行了介绍,并着重介绍了能够避免输出爆炸灾难的合并操作,这一节我们来关注信道弱化与强化操作. [1]<Chan ...

  8. 进入css3动画世界(一)

    其实我做css3动画也没有多久,这篇文章目标人群是css3动画的新手,不喜勿喷. 分类 目前我接触到的css3动画有2类:一种是transition的,另一种是@keyframes的. 两者的区别就是 ...

  9. Bmob云IM实现头像更换并存入Bmob云数据库中(1.拍照替换,2.相册选择)

    看图效果如下: 1.个人资料界面 2.点击头像弹出对话框 3.点击拍照 4.切割图片,选择合适的部分 5.点击保存,头像替换完毕,下面看从相册中选择图片. 6.点击相册 7.任选一张图片 8.切割图片 ...

  10. K相邻算法

    刚开始学习机器学习,先跟这<机器学习实战>学一些基本的算法 ----------------------------------分割线--------------------------- ...