13个不可不知的ASP.NET MVC扩展点 |
本文标签:ASP.NET MVC扩展 ASP.NET MVC设计的主要原则之一是可扩展性 。处理管线(processing pipeline)上的所有(或大多数)东西都是可替换的 。因此,如果您不喜欢ASP.NET MVC所使用的约定(或缺乏某些约定),您可以创建自己的服务来支持您的约定,并将其注入到主管线中 。 在本文中,我们将从管线开始直到视图呈现,逐一向您展示每个ASP.NET MVC开发者都必须了解13个扩展点 。 1.ASP.NET MVC扩展之RouteConstraint 通常情况下你可以使用正则表达式对url参数进行约束,但如果您的约束不仅仅取决于单一参数,您可以实现IRouteConstrains的方法,并在其中添加你的验证逻辑 。 比如对日期的验证,url中可能会包含年、月、日,而你需要验证这三者是否可以组合成一个有效的日期 。 2.ASP.NET MVC扩展之RouteHandler RouteHandler是在路由选择之后进行处理的组件,它并不仅仅针对ASP.NET MVC 。显然,如果您改变了RouteHandler,那么对请求的处理将不再使用ASP.NET MVC,但这在您使用其他HttpHandler或经典的WebForm进行路由处理时却是非常有用的 。 3.ASP.NET MVC扩展之ControllerFactory ControllerFactory是基于路由的组件,它选择正确的controller并对其实例化 。default factory会查找实现了IController并且以Controller结尾的类,然后通过反射使用无参构造函数进行实例化 。 但如果您希望使用依赖注入,就不能再使用default factory,而必须使用支持IoC的controller factory 。MvcContrib和Ninject Controller Factory都包含支持IoC容器的controller factory 。 4.ASP.NET MVC扩展之ActionInvoker ActionInvoker顾名思义是负责调用(invoke)action的 。默认的action invoker通过方法名、action名或其他可能的selector attribute来查找action,然后调用action方法以及定义的filter,最终执行得到action result 。 你会发现大部分执行管线存在于ControllerActionInvoker类的逻辑之中 。因此,如果希望改变这些约定,如action方法的选择逻辑、http参数映射到action参数的方式、选择和执行filter的方式等,您需要扩展该类并重写需要修改的方法 。 可以参阅NinjectActionInvoker I developed to allow injection of dependencies inside filters 。 5.ASP.NET MVC扩展之ActionMethodSelectorAttribute 使用默认的action invoker时,action的选择是基于名称的 。您也可以实现自己的Method Selector以改善对于action的选择 。在框架中已经包含了AcceptVerbs特性,它允许您指定使用哪一个HTTP Verb来处理action的响应 。 例如,您也许会希望基于浏览器所支持的语言或浏览器类型(如移动设备的浏览器或桌面浏览器)来进行action的选取 。 6.ASP.NET MVC扩展之AuthorizationFilter 这种过滤器是在action执行之前执行的,用来确保请求是有效的 。 框架中已经包含了一些autorization过滤器,最有名的莫过于Authorize特性,它用来检查当前用户是否允许执行该action 。另一个是用来阻止CSRF攻击的ValidateAntiForgeryToken 。如果您希望实现自己的authorization,那么必须实现接口 。例如,日期中的小时 。 7.ASP.NET MVC扩展之ActionFilter Action Filters在action执行前后执行 。OutputCache过滤器是几个核心过滤器之一 。这可能是您最有可能使用的扩展点,并且在我看来,controller只关心它的主要工作,而view所需要的所有其他数据都必须从action过滤器内部获取,这样的实现对于一个组织良好的view来说,是十分关键的 。 8.ASP.NET MVC扩展之ModelBinder 默认的model binder使用参数名称进行HTTP参数到action方法参数的映射 。例如,http参数user.address.city将映射到方法参数user的Address属性的City属性 。DefaultModelBinder也同样适用于数组和其他列表类型 。 更进一步来说,例如,您可能希望从数据库中进行检索,直接根据person的id将其转换为Person对象 。Timothy Khouri(网名SingingEels)在他的文章Model Binders in ASP.NET MVC中更好的阐述了这种方法 。他的代码基于Preview 5,但其理念是一样的 。 9.ASP.NET MVC扩展之ControllerBase 所有的Controller均继承自基类Controller 。要想在action中封装自己的逻辑和约定,创建自己的父类使所有Controller继承自该类,是一种很好的方式 。 10.ASP.NET MVC扩展之ResultFilter 与ActionFilter类似,ResultFilters在ActionResult前后执行 。OutputCache过滤器也可以作为ResultFilter的示例 。另外,比较常用的诠释这种过滤器的示例是日志记录 。如果您希望在页面返回给用户时记录日志,可以编写自定义的RenderFilter,在ActionResult执行之后记录日志 。 11.ASP.NET MVC扩展之ActionResult ASP.NET MVC提供了很多result用来呈现视图、JSON、纯文本、文件并重定向到其他action 。如果您需要其他类型的result,可以自定义ActionResult,并实现ExecuteResult方法 。例如,如果您希望将PDF文件作为结果发送,您需要使用PDF库编写能够生成PDF的ActionResult 。又如RSS feed,可参见how to write a RssResult in this post 。 12.ASP.NET MVC扩展之ViewEngine 您可能不需要编写自己的view engine,但您也许可以考虑使用其他引擎来替代默认的WebForm view engine 。在我看来,最有趣的引擎就是Spark 。 如果您确实希望编写自己的view engine,可以看一下Brad Wilson的文章: Partial Rendering & View Engines in ASP.NET MVC 。 13.ASP.NET MVC扩展之HtmlHelper 视图必须十分简单整洁,它们只能包含html标记并调用HtmlHelper的辅助方法 。视图中不能包含任何代码,所以辅助方法必须十分方便,使您可以将代码从视图中提取出来,放到一个可测试的环境中去 。正如Rob Conery所说:如果有if,就构造辅助方法(If theres an IF, make a Helper) 。 什么是HtmlHelper辅助方法?其实就是HtmlHelper类的扩展方法,这是唯一的要求 。 你可以从Rob的文章Avoiding Tag Soup中了解到为什么说HtmlHelper是封装视图中代码的好方法 。 在您的应用中该使用哪个呢? 正如您所猜测的那样,并不是所有的应用都需要扩展以上的13个扩展点 。最可能在所有应用中进行扩展的是ActionFilter和HtmlHelper 。另外,您很可能会使用其他人编写的扩展,如使用了IoC容器的ControllerFactory或用来摆脱WebForm的ViewEngine 。 但是,学习这些扩展点并进行尝试是十分重要的,这样您才会做出选择,并随时准备在必要的时候使用这些强大的扩展点 。下周我将发表一些文章来阐述如何使用这些扩展点 。 |