2.1.5根据路由规则生成URL
前面已经提到过ASP.NET的路由系统主要有两个方面的应用,一个是通过注册路由模板与物理文件的映射实现请求URL和物理地址的分离,另一个则是通过注册的路由规则生成一个完整的URL,后者通过调用RouteCollection对象的GetVirtualPath方法来实现。
如下面的代码片段所示,RouteCollection定义了两个GetVirtualPath方法重载,他们共同的参数requestContext和values分别代表请求上下文(RouteData和HTTP上下文的封装)和用于替换定义在路由模板中的变量占位符的路由变量。另一个GetVirtualPath方法具有一个额外的字符串参数name,他表示集合中具体使用的路由对象的注册名称(调用MapPageRoute方法时指定的第一个参数)。
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
如果调用GetVirtualPath方法时没有指定具体生成虚拟路径的Route对象,那么该方法会遍历整个路由表,直到找到一个路由模板与指定的路由参数列表相匹配的Route对象,并返回由它生成的VirtualPathData对象。具体来说,该方法会依次调用路由表中每个Route对象GetVirtualPath方法,直到该方法返回一个具体的VirtualPathData对象为止。如果调用所有Route对象的GetVirtualPath方法的返回值均为Null,那么整个方法的返回值也为Null。
在调用GetVirtualPath方法的时候可以传入Null作为第一个参数(requestContext),在这种情况下它会根据当前HTTP上下文(对应于HttpContext的静态属性Current)创建一个RequestContext对象作为调用Route对象GetVirtualPath方法的参数,该方法的参数,该参数包含一个空的RouteData对象。如果当前HTTP上下文不存在,则该方法会直接抛出一个类型为InvalidOperationException的异常。
Route对象针对GetVirtualPath方法而进行的路由解析只要求路由模板中定义的变量的值都能被提供,而这些变量值具有3种来源,分别是Route对象中为路由变量定义的默认值、指定RequestContext对象的RouteData中提供的变量值(Values属性)和额外提供的变量值(通过values参数指定的RouteValueDictionary对象),这3种变量值具有由低到高的优先级。
同样以之前定义的关于获取天气信息的路由模板为例,我们在Weather.aspx页面的后台代码中按照如下方法通过RouteTable的静态Routes得到代表全局路由表的RouteCollection对象,并调用其GetVirtualPath方法生成3个具体的URL。
public partial class Weather : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { RouteData routeData = new RouteData(); routeData.Values.Add("areaCode", "0512"); routeData.Values.Add("days", "1"); RequestContext requestContext = new RequestContext(); requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current); requestContext.RouteData = routeData; RouteValueDictionary values = new RouteValueDictionary(); values.Add("areaCode", "028"); values.Add("days", "3"); Response.Write(RouteTable.Routes.GetVirtualPath(null, null).VirtualPath+ "<br/>"); Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath + "<br/>"); Response.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath + "<br/>"); } }
由上面的代码片段可以看到,第一次调用GetVirtualPath方法传入的requestContext和values参数均为Null;第二次则指定了一个手工创建的RequestContext对象,其RouteData的Values属性具有两个变量(areaCode = 0512;days = 1),而values参数依然为Null;第三次则同时为参数requestContext和values指定了具体的对象,后者包含两个参数(areaCode=028;days=3)。