代码改变世界

ASP.NET MVC之初体验

2008-09-11 17:30  JimLiu  阅读(482)  评论(0)    收藏  举报

最近开始接触ASP.NET MVC(以下简称MVC),已经是Preview 5版本了,估计正式版都快出来了,而很多资料还停留在Preview 3、4的程度,给我的学习造成一定困难。不过还好。

MVC给我的第一感觉就是思路清晰——通过URL来驱动,由于URL是可以包含语义的(事实上,我们在MVC中也是靠尽量让URL拥有语义来帮助我们的),也就是说一个好的URL不仅可以让它更好看——想想www.xxx.com/space.aspx?user=JimLiu还是www.xxx.com/space/JimLiu给人的感觉更好呢?而且这样的URL可以让我们开发者的思路更清晰——URL决定了业务。

这样的话开发的时候会省事不少,最直接的表现就是原来我们经常通过在CodeBehind中用控件属性或者Request[]来获取数据,而现在我们可以直接通过Action方法的参数,比如一个Register方法,不仅可以把username, password传入,甚至可以动态构建一个User对象传入,这样无疑是很方便的。虽然这里还有很多问题,比如把验证的压力交给了客户端等等,但我相信这种发展的趋势是好的,微软以后也肯定会改善。

同时还有省事的是在输出数据的时候,我们就不再需要去费事地写一个控件的OnDataBinding之类的事件,来控制它输出的细节了,因为在MVC中输出我们通常都用内联服务端代码的方式来输出了。有朋友觉得这样做会退化到ASP那种逻辑代码和视图混在一起的情况了,我觉得不然——我们所强调的是“业务逻辑”不应该和视图混淆在一起,而在MVC中我们使用内联服务端代码的方式来输出HTML,并不是“业务逻辑”,而是“表现逻辑”,既然是表现逻辑,当然应该处于表现层了。而业务逻辑呢?当然是由Controller的Action方法来完成。

经过一段时间尝试之后,我决定使用MVC框架重写我们的Online Judge——原来是直接在Code Behind里拼接SQL的、只求能用但是代码极其混乱的应用。虽然MVC给了我很大的便利,但是同时也带来了不少麻烦。下面就谈谈我遇到的一些麻烦和对应的解决方案。

一、对于MasterPage中的业务逻辑,我没有想到一种优雅的方式来解决,同时困扰我的还有一个Action中,如果需要要求页面引用js, css文件,或者注册一个脚本块等,也不大方便。对于前一个问题,我目前还没有好的办法,有朋友提出使用ActionFilter来解决,我觉得不爽,因为ActionFilter是得作为Attribute来标记的,那这样一来我如果在ActionFilter中处理母版页的事情,不是得在用到这个母版页的Action或者Controller上都标记个Attribute了?Attribute是什么?是“特性”,而既然母版页是“共性”,我觉得就不应该用Attribute来解决它。

后一个问题,我使用了一种很“龌龊” 的方法,就是往ViewData里写东西,比如我约定一个ViewData["Scripts"]是一个IList<string>,然后我在母版页里foreach这个IList来注册脚本。

二、Authentication的问题。根据网上的资料,普遍解决Authentication的方法是用ActionFilter,我现在采用的也是这种方法。总的来说我还是觉得这样实现是不错的,但是还是有不爽的地方。

最突出的一点就是ReturnUrl了,我采用了两个Action,一个是/Security/SignIn,一个/Security/SignOut,显然,用于登录、登出,由于我需要ReturnUrl,所以我一定得在通向这两个Action的表单/ActionLink中传入这个ReturnUrl,这样的要求是什么?我在实现一个指向SignIn的表单的时候就必须给这表单的action带上个ReturnUrl参数,指向现在的页面,这还不算,我的MasterPage中有个ActionLink指向SignOut也得带个QueryString了——不知为何这总让我觉得不大自然,虽然我承认这无伤大雅。但我坚信在以后的版本中会有更健全的Authentication & Authoriation机制。

这里还遇到另一个有趣的问题,那就是在我SignIn的时候,是存在成功不成功的,但是我需要做到的是:无论成功与否,都必须返回到ReturnUrl,但是根据不同的结果,再去给出一个提示,比如一个简单地alert('登录失败'),这就麻烦了点。我只能想到那个同样“龌龊”的方法,就是往TempData的约定条目里写东西,然后还是在MasterPage里判断该给什么提示。这样做也太损了点,而且好像TempData是需要SessionState的,这点就很弱啊,因为为了性能我正考虑关闭SessionState呢,而且本来往Session里写东西就不是个好行为。不知道有没有朋友有好的解决方案。

三、同一个页面不同的访问情况的问题。有时候我们的页面是“全能” 的——表单提交之前,它这么干,表单提交之后,它那么干。如何优雅地解决这个问题呢?通过一个巨大的if{}else{}来判断显然不爽。经过搜索我发现现在版本的MVC中已经有比较好的解决方案了,那就是.NET中的神奇的Attribute,对重载的Action方法,通过标记AcceptVerbs这个Attribute来确定哪个处理Post哪个处理Get,表单提交前我们显然是在Get,提交之后嘛,就处理Post好啦,这就方便多了。

总的来说我觉得ASP.NET MVC还是一个很优秀的框架,可以帮助我们解决很多问题。我也相信在以后的版本中它会越来越好。对于上文中提出的几个问题,希望有经验和心得的朋友提供点指点。