从路径选择系统构建输出的URL
在本文的前面,我说过ASP.NET MVC路径选择系统负责两件事情:
把进来的URL映射到处理的Controllers/Actions上
帮着构建可以在以后用来回调Controllers/Actions的输出到客户端的URL(例如,表单提交, < a href="">链接, 和 AJAX 调用等等)
URL路径选择系统有不少辅助方法和类,方便你在运行时动态查看和构建URL(你也可以直接对RouteTable的Route集合进行操作来查看URL)。
Html.ActionLink
在本博客系列的第一部分,我简单地讨论了Html.ActionLink()视图辅助方法。它可以在视图里使用,允许你动态地生成 < a href=""> 超链接。比较酷的是,它可以使用MVC路径选择系统里定义的URL映射规则来生成这些URL。例如,下面2个Html.ActionLink 调用:
automatically pick up the special Search results route rule we configured earlier in this post, and the "href" attribute they generate automatically reflect this: 会自动地使用我们在本贴子前面配置的的特殊查询结果路径规则,它们自动生成的href属性反映了这个情况:
特别地,注意上面,Html.ActionLink的第二个调用自动地把page参数映射成URL的一部分(也注意,第一个调用省略了page参数值,因为它知道服务器端会自动提供默认值)。
ASP.NET MVC路径:Url.Action
除了使用Html.ActionLink外,asp.net mvc还有个Url.Action()视图辅助方法。该方法生成原生的字符串URL,然后你可以任何方式来使用它们。例如,下面的代码片段:
会使用URL路径选择系统返回下面这个原生的URL(而不是包装在 < a href=""> 元素里):
ASP.NET MVC路径:Controller.RedirectToAction
asp.net mvc还提供了Controller.RedirectToAction()辅助方法,你可以在控制器里使用来进行转向操作(URL是使用URL路径选择系统计算出来的)。
例如,当在控制器里调用下面代码时:
在内部,它会生成一个对Response.Redirect("/Search/Beverages")的调用。
DRY (别重复自己)
上述所有的辅助方法的好处在于它们允许我们避免在我们的控制器和视图逻辑中硬写URL。如果在后来我们决定改变查询URL路径映射规则,从"/Search/[query]/[page]" 改回到 "/Search/Results/[query]/[page]" 或者 "/Search/Results?query=[query]&page=[page]" ,我们只要在一个地方(我们的路径注册代码中)做编辑,就可以轻松搞定。我们不需要改动视图或控制器中的任何代码,就可以捡起新的URL(这就坚持了“DRY原则”)。
使用Lambda表达式从路径选择系统构建输出的URL
前面的URL辅助方法例子使用了VS 2008中VB和C#现在支持的新的匿名类型。在上面的例子中,我们使用了匿名类型来有效地传入一串名称/数值对,用以帮助映射URL(你可以把这想像为生成字典的一个比较干净的方式)。
除了使用匿名类型以动态方式传递参数外, asp.net mvc框架还支持使用强类型机制创建action路径的能力,这些强类型机制为URL辅助方法提供了编译时检查和intellisense。这是通过使用泛型和新的VB和C#对Lambda表达式的支持来实现的。
例如,下面这个匿名类型 ActionLink 调用:
也可以写成:
除了写起来简短外,这第二个选项还有类型安全的好处,这意味着你得到对表达式的编译时检查以及Visual Studio的代码intellisense(你还可以使用重构工具对它进行重构):
注意上面,我们是如何使用intellisense挑选出我们想用的SearchController的Action方法的,以及参数是强类型的。生成的URL都是由asp.net mvc url路经选择系统驱动的。
你也许在想,这到底是怎么回事呢?如果你还记得,8个月前,我在博客里讨论Lambda表达式时,我谈到了Lambda表达式既可以编译出成代码代理(delegate),也可以编译成表达式树对象,然后在运行时可以用来分析Lambda表达式。对于Html.ActionLink< T> 辅助方法,我们使用这个表达式树选项,然后在运行时分析对应的lambda,查出它调用的action方法以及相关的参数类型,在表达式中指定的名称和值等。然后我们可以在MVC URL路径选择系统中使用这些信息, 返回合适的URL和相关联的HTML。
重要注意事项: 当使用这Lambda表达式方法时,我们实际上从不运行对应的Controller action方法。例如,下面的代码并不调用我们的SearchController中"Results" action方法:
实际上,它只是返回这个HTML超链接:
如果这个超链接被用户点击的话,它会向服务器发回一个请求,该请求会调用SearchController的Results action方法。
单元测试路径
asp.net mvc框架的一个核心设计原则是促进很好的测试支持。 跟mvc框架的其他部分一样,你可以轻松地单元测试路径和路径匹配规则。mvc路径选择系统可以独立于asp.net生成实例和运行,这意味着你可以在任何单元测试库里装载和单元测试路径模式(而不用启动web服务器),可以使用任何单元测试框架(NUnit, MBUnit, MSTest等等)。
虽然你可以在你的单元测试中直接单元测试一个asp.net mvc应用的全局RouteTable映射集合,但一般来说,让单元测试改变或者依赖于一个全局的状态不是一个很好的主意。一个你可以使用的较好的模式是,把你的路径注册逻辑放在一个象下面这样的RegisterRoutes()辅助方法中,对作为参数传入的RouteCollection进行操作(注:我们也许会把这个模式在下个预览版更新中做成默认的VS模板模式):
然后,你可以编写单元测试,创建自己的RouteCollection实例,调用Application的RegisterRoutes辅助方法,在其中注册应用的路径选择规则。然后,你可以向应用发出模拟请求,核实这些请求确有注册了的正确的控制器和action方法,而不用担心任何副作用:
希望这个贴子提供了关于asp.net mvc路径选择架构工作原理的一些细节,以及你如何可以使用它来定制发布在你的asp.net mvc应用中的url的结构和布局。
在默认情形下,在你创建一个新的asp.net mvc Web应用时,它会预先定义一个你可以使用的默认的 /[controller]/[action]/[id] 路径选择规则,而不必手工配置或启用什么。这应该允许你不用注册你自己的自定义路径选择规则,就可以建造许多应用。但希望上面的内容示范了,如果你想对你自己的url格式做自定义结构的话,做起来并不难, mvc框架对此提供了许多的功能和灵活性。
【编辑推荐】
- 如何在IIS6.0中部署asp.net mvc程序
- 用Winform傻瓜式搭建asp.net mvc框架
- ASP.NET Session失效的编程思路
- ASP.NET Session 状态的存储
- 了解ASP.NET Web应用程序模型