Chad 2009-10-15
从微软今年4月正式发布ASP.NET MVC 1.0以来,已经有半年,而从去年的预览版开始算,更是已经有一年多时间了。但是我由于我的inluck.net所在的虚拟主机只支持.NET Framework 2.0,要升级到ASP.NET MVC 1.0所要求的.NET Framework 3.5需要一大笔钱,所以我就一直没有去试用MVC开发ASP.NET网站。
前几天,突然决定再次把“改版inluck”提上日程,想来想去,还是用MVC架构好。我试过按Scott Hanselman去年7月在他博客上发的贴“Deploying ASP.NET MVC on ASP.NET 2.0”里所介绍的方法( http://www.hanselman.com/blog/DeployingASPNETMVCOnASPNET20.aspx ),想将ASP.NET MVC 1.0放在.NET Framework 2.0下运行,可惜,没有成功,可能是正式版的MVC里使用了.NET Framework 3.5里的新特性吧。最后,我决定用新环境,所以在Qdog那里买了个新的3.5的主机。
ASP.NET MVC 1.0的内置身份验证
用VS2008新建MVC网站时,生成的模版里已经自带了注册和登录功能。这里说一下它里面用户身份验证。.NET 2.0时代,内置的Membership要验证用户身份时只需检查User.Identity.IsAuthenticated。而在MVC 1.0里,就更方便了,只需要在Action方法前加上一个Authorize属性,没有登录的用户在访问该Action时会被转向到web.config里authentication节点的子节点forms的属性loginUrl所指定的路径。
自定义身份验证
这很好,但是如果我想自定义一套用户身份验证方法,而又想像MVC 1.0那样在Action前加一个属性就搞定,该怎么做呢?由于对属性类很陌生,我就查了下资料,MSDN上的文档在这里http://msdn.microsoft.com/zh-cn/library/system.attribute.aspx
具体做法,我在这里找到了其中一种http://davidhayden.com/blog/dave/archive/2009/04/09/CustomAuthorizationASPNETMVCFrameworkAuthorizeAttribute.aspx
该做法简单地说,就是自定义一个属性类,并继承MVC 1.0所用的那个AuthorizeAttribute,然后再重写AuthorizeAttribute的AuthorizeCore方法,并把自定义的验证结果作为返回值返回就OK了,如下:
- // C#
- public class CustomAuthorizeAttribute : AuthorizeAttribute
- {
- public IAuthorizationService _authorizationService { get; set; }
- protected override bool AuthorizeCore(HttpContextBase httpContext)
- {
- return _authorizationService.Authorize(httpContext);
- }
- }
自定义filter类
其实在找到这种做法前,我就有想到过自已写一个属性类,可是我试过在Action前加上继承了Attribute类的自定义属性类,却发现在运行时,属性类没有被调用。毕竟,属性就是属性,本身只是个元数据。。。
但是,我觉得还是有办法可以使得其在Action执行前就被调用的,因为Mvc 1.0的AuthorizeAttribute就是例子。后来我查了查AuthorizeAttribute的构成(http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx),它的父类是FilterAttribute,并实现了IAuthorizationFilter接口。关键就在于这个父类FilterAttribute,如果Action附加了该属性类或者派生于其的属性类,那么属性类的构造函数就会先于Action被调用。真是名副其实的“Filter”啊!有了它,我们就可以做很多有趣的事了,例如自定义自己的aciotn filter。
后来,我发现原来MVC 1.0里已经有一个ActionFilterAttribute,它是在FilterAttribute的基础上,再实现了IActionFilter和IResultFilter这两个接口。实现了IActionFilter和IResultFilter,我们就可以做更多有趣的事了。IActionFilter里有两个方法OnActionExecuted和OnActionExecuting,分别会在action执行后和执行中被调用。而IResultFilter里也有两个方法OnResultExecuted和OnResultExecuting分别会在action的result执行后和执行中被调用。
综上,要自定义filter属性类(附加给action时,会在action执行前先调其构造函数)时,可以选择继承FilterAttribute或者ActionFilterAttribute,继承后者可以做更多有用的事。而如果只想自定义用户身份验证并还想用ASP.NET已经做好的非登录重定向功能,则可选择继承AuthorizeAttribute并重写其AuthorizeCore方法。