5.根据路由规则生成url
ASP.NET路由系统主要有2个方面的应用:通过注册路由模板与物理文件路径的映射实现url和物理地址的分离;通过注册的路由规则生成完整的url;前者通过RouteCollection对象的GetRouteData方法实现,后者通过RouteCollection对象的GetVirtualPath方法实现。再来看看GetVirtualPath这个方法
//共同的参数requestContext表示请求上下文,也就是RouteData和Http上下文的封装, //values表示用于替换模板中占位符的路由变量 public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); //name参数表示集合中具体使用的路由对象的注册名称,也是调用MapPageRoute方法时的第一个参数 public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
在调用这个方法时,如果没有指定存有路由变量的Route对象时,那么该方法会遍历整个路由表,直到找到一个路由模板与指定的路由参数相匹配的Route对象。具体的情况是,该方法遍历Route对象的GetVirtualPath方法,直到返回一个具体的VirtualPathData对象为止,如果每个方法都返回null,那么最后整个方法也返回null。
这个方法的参数有三种来源:Route对象中为变量定义的默认值;指定RequestContext对象的RouteData中提供的变量值(Values属性);额外提供的变量值,通过values参数指定的RouteValueDictionary对象;且这三种变量具有由低到高的选择优先级。
6.MVC里的路由
对于ASP.NET MVC应用来说,请求的目标不再是一个具体的物理地址,而是控制器里的方法。MVC里的路由是对ASP.NET进行了一个扩展,最主要的就是为RouteCollection类型定义了一系列的扩展方法,这些扩展方法是定义在RouteCollectionExtensions类里的,命名空间为System.Web.Mvc下。下面来看看这个类的一部分方法
public static class RouteCollectionExtensions { //这里与RouteCollection类里的Ignore是一样的原理 public static void IgnoreRoute(this RouteCollection routes, string url); public static void IgnoreRoute(this RouteCollection routes, string url, object constraints); //这里与RouteCollection类里的MapPageRoute是一样的原理,它还有多个重载 public static Route MapRoute(this RouteCollection routes, string name, string url); public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults); }
由于MVC模式是采用控制器,方法的方式定义路径,不是真真的物理路径与路由之间的映射,因此MapRoute和IgnoreRoute方法的参数有些变化。对于某个请求来说,如果路由表与之匹配,则匹配的Route对象的GetRouteData方法被调用并返回一个具体的RouteData对象。
7.基于Area的路由映射
对于较大规模的Web应用,我们可以采用区域的方式,每一个area都是一个独立的子系统,包含了Models、Views和controller在内的目录结构和配置文件,每个area都有自己的路由规则,基于area的路由映射通过AreaRegistration类型进行注册。
public class PersonnalMangerAreaRegistration : AreaRegistration { public override string AreaName { get { return "PersonalManger"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "PersonnalManger_default", "PersonalManger/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional }, //控制器所在命名空间 new string[1] { "PersonalManger" } ); }
}
上面是我做的一个例子,这提供了如何注册区域路由的方法,接下来要了解本质学习AreaRegistration和AreaRegistrationContext类。AreaRegistration类是一个抽象类,抽象只读属性AreaName返回当前区域的名称,而抽象方法RegisterArea用于实现基于当前area的路由注册。这个类还提供了2个抽象的静态RegisterAllAreas方法:
public static void RegisterAllAreas(); public static void RegisterAllAreas(object state);//state表示传递给具体AreaRegistration的数据
当RegisterAllAreas方法被执行时,所有当前Web应用直接或间接引用的程序集会被加载(如果没有加载),MVC路由机制会从这些程序集中解析出所有继承AreaRegistration的类,并通过反射创建对应的AreaRegistration对象,同时一个作为Area注册上下文的AreaRegistrationContext 对象也被创建。不同于一般的路由注册,通过AreaRegistration实现的针对区域的路由注册具有一些细微的差异,体现在生成的DataTokens里多了2个属性,分别为area和UseNamespaceFallback属性,area代表区域的名称,后者表示是否需要使用后备的命名空间,如果显示指定了命名空间的话,则此属性为false。AreaRegistration类所生成的命名空间属性不是简单的加了一个命名空间字符串,而是还加了一个.,比如myWeb命名空间,则属性值为myWeb.*。