在传统的ASP.NET应用程序中,发生一个请求之后将映射到一个.aspx文件,且会对应到一个具体的物理aspx文件。ASP.NET MVC Framework中,进入一个请求之后,不再是映射到.aspx文件,而是由MVC Framework中提供的路径选择引擎,映射到正确的Controller和Action执行请求。ASP.NET MVC Framework中URL路径映射规则定义在Global.asax中,这在一定程序上带来了很多的灵活性,如果想要修改URL应用结构的话,只需要修改一下映射规则即可,并不需要修改Controller和View中的代码,但是这仍然不够灵活。改变Global.asax代码仍然会导致应用程序的重新编译,本篇文章末尾部分将会介绍如何通过HttpModule定义映射规则在Web.config中。
先看一下下面这幅图:
从上图中可以看到,发生一个请求之后,第一步就是路径选择,而映射规则是通过在Routes集合中添加Route实例来注册的,如:
RouteTable.Routes.Add( new Route { Url = "[controller]/[action]", Defaults = new { action = "Index"}, RouteHandler = typeof(MvcRouteHandler) });
Route中有四个属性,它的定义如下:
public class Route { public Route(); public Route(string url, Type routeHandler); public Route(string url, object defaults, Type routeHandler); public object Defaults { get; set; } public Type RouteHandler { get; set; } public string Url { get; set; } public object Validation { get; set; } }
其中:
Url指定了请求的Url匹配规则,还定义了URL应该如何分割成(tokenized)不同的参数,URL中可替换的参数,是通过 [参数名称] 的句法来定义的。
Defaults属性定义了一个默认值的字典,可以在进来的URL并不包含某个指定的参数值的情形下使用。
RouteHandler属性定义了在URL被分割成参数,适当的路径选择规则被确定之后,应该用来处理请求的 IRouteHandler 实例。
Validation属性允许我们指定一个路径选择规则匹配需要满足的先决条件,如对参数值使用正则表达式,来过滤一个路径选择规则是否匹配。
在使用ASP.NET MVC Framework时,要注意一点II6和II7的区别,如果在II7下,不需要使用.mvc扩展名,路径选择规则可以如下所示:
RouteTable.Routes.Add( new Route { Url = "[controller]/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(MvcRouteHandler) });
而在II6下,控制器名后面必须要有.mvc扩展名:
RouteTable.Routes.Add( new Route { Url = "[controller].mvc/[action]/[id]", Defaults = new { action = "Index", id = (string)null }, RouteHandler = typeof(MvcRouteHandler) });
在本文第二节我们提到过Route的一个Validation属性,允许我们指定一个路径选择规则匹配需要满足的先决条件。如下代码段所示,验证Id必须为整数且长度在1到8之间:
RouteTable.Routes.Add( new Route { Url = "Blog.mvc/Detail/[id]", Defaults = new { controller = "Blog", action = "Detail" }, Validation = new { id=@"/d{1,8}" }, RouteHandler = typeof(MvcRouteHandler) });
在ASP.NET MVC Framework中,提供了很好的扩展功能,如我们可以自定义RouteHandler来实现在Web.config中配置ControllerFactory和ViewFactory。在ASP.NET MVC Framework中,自定义RouteHandler只需要实现IRouteHandler接口并实现GetHttpHandler方法,它的定义如下:
public interface IRouteHandler { IHttpHandler GetHttpHandler(RequestContext requestContext); }
public class RouteBuilder : IHttpModule { public void Init(HttpApplication application) { RouteConfiguration routeConfig = (RouteConfiguration)System.Configuration.ConfigurationManager.GetSection("RouteTable"); foreach (RouteElement routeElement in routeConfig.Routes) { Route currentRoute = new Route(); currentRoute.Defaults = new DefaultsType(routeElement.Defaults); currentRoute.Url = routeElement.Url; currentRoute.RouteHandler = typeof(MvcRouteHandler); RouteTable.Routes.Add(currentRoute); } } public void Dispose() { } }
关于ASP.NET MVC Framework中的路径选择就简单的介绍到这儿了,其实本篇文章后两节都是在推荐一些学习的资料,而关于路径选择的详细内容,在ScottGu的文章里已经写的很仔细了。
最后,再次做个小广告:我在博客园社区中创建了一个Web技术联盟小组,欢迎大家加入。同时,该小组将在近期会有一些活动,来提高社区的氛围:)
作者:TerryLee