日期:2014-05-16 浏览次数:21224 次
Filter是很好的实现crosscutting concern 的方式,常见的crosscutting concern包括log,验证,缓存,异常处理(笔者推荐postsharp),等等。
什么是crosscutting concern?
为了更好的专注业务的实现,降低耦合,提高内聚。因此把这些concern从业务中抽离出来解决,可以更好的维护,更改和扩展。它们也构成了架构中cross-cutting的部分,可以在与业务隔离的情况下,统一编码,测试,修改。
例如AdminController :
public class AdminController : Controller {
// ...instance variables and constructor
public ViewResult Index() {
if(!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
}
public ViewResult Create() {
if(!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
}
public ViewResult Edit(int productId) {
if(!Request.IsAuthenticated) {
FormsAuthentication.RedirectToLoginPage();
}
}
}
我们的目的很明确,我需要限制这个controller的访问,只有登录的才能访问,那么我们每个action都要加上Request.IsAuthenticated.如果需要限制role,指定用户才能访问,我们就要写一个验证函数,并修改全部的action。
[Authorize]
public class AdminController : Controller {
public ViewResult Index() {
}
public ViewResult Create() {
}
public ViewResult Edit(int productId) {
}
}
好处:可以看到filter提高了代码的可读性,减少了重复。
FilterAttribute的逻辑注入在http pipeline里面,在controller之前,反射出所有controller,查找customize的attribute,如果有加Authorize,调用相应的login验证函数(后续章节会介绍),验证不通过则返回401 。
Attribute是.net 中很好应用装饰模式的例子,通过继承自System.Attribute,可以实现自己的attribute,包括class,method,property,field。目的是动态的注入property,member,和ability到相应的类中,编译之后,生成的IL已经注入了attribute要提供的能力。通常的AOP框架中有attribute和IL wave 一起使用的代码和使用方法。不熟悉的读者可以查阅相关MSDN,本章所有内容都建立在attribute有一个基本的认识上的。
MVC中四种基本的filter
|
Authorize Filter |
验证。进入controller或action之前 |
|
Action Filter |
进入action前后会被调用 |
|
Result Filter |
Execute result的前后会被调用 |
|
Exception Filter |
Filter,action,或者execute result时发生异常时被触发 |
MVC中的authorizefilter除了可以加在class上(前面演示过了),还可以针对action做filter:
public class AdminController : Controller {
[Authorize]
public ViewResult Index() {
}
[Authorize]
public ViewResult Create() {
}
}[Authorize(Roles="trader")]
public class ExampleController : Controller {
[ShowMessage]// applies to just this action
[OutputCache(Duration=60)]// applies to just this action
public ActionResult Index() {
// ...action method body
}
} public class BlockAttribute : AuthorizeAttribute {
public BlockAuthAttribute() {
}
protected override bool AuthorizeCore(HttpContextBase httpContext) {
return false;
}
}
作为演示,实现了一个block attribute,加上这个attribute会block所有的request。现实场景中,拿到了httpContext可以做很多事情,因为里面的对象包含的信息非常丰富。
使用:
[Block]
public string Index() {
return "Always block ";
}
访问页面会发现:

由于我创建的是basic的项目,没有加login view在Account,因