ASP.NET的路由系统:根据路由规则生成URL

前面我们已经提到过,ASP.NET 的路由系统主要具有两个方面的应用,其一就是通过注册URL模板与物理文件路径的匹配实现请求地址和物理地址的分离;另一个则是通过注册的路由规测生成一个相应的URL。后者通过调用RouteCollection类型的GetVirtualPath方法来实现。[源代码从这里下载]

如下面的代码片断所示,GetVirtualPath定义了两个GetVirtualPath方法重载,它们共同的参数requestContext和values分别表示请求上下文(RouteData和HTTP上下文的封装)和用于替换定义在URL模板中的变量站位符的值。另一个GetVirtualPath方法具有一个额外的字符串参数name,它表示集合中具体使用的路由对象的注册名称(调用MapPageRoute方法时指定的第一个参数)。而AppendTrailingSlash和LowercaseUrls决定在对生成的URL进行规范化的时候是否添加一个“/”字符(如果没有),以及是否需要将URL转化为小写。

   1: public class RouteCollection : Collection<RouteBase>
   2: {    
   3:     //其他成员
   4:     public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
   5:     public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
   6:          
   7:     public bool AppendTrailingSlash {  get;  set; }
   8:     public bool LowercaseUrls {  get;  set; } 
   9: }

如果调用GetVirtualPath方法时没有指定具体采用的路由对象,会遍历整个集合的每个路由对象并调用其GetVirtualPath方法,如果返回的VirtualPathData不会Null则直接将其作为返回值;否则(找不到匹配的路由对象)返回Null。如果在调用GetVirtualPath确定了具体使用的路由对象,则直接调用该路由对象的GetVirtualPath方法并返回其执行结果。

我们在调用GetVirtualPath方法的时候可以传入Null作为第一个参数(requestContext),在这种情况下会基于当前HTTP上下文(对应于HttpContext的静态属性Current)创建一个RequestContext对象作为调用路由对象GetVirtualPath方法的同名参数,该参数包含一个空的RouteData对象。如果当前HTTP上下文不存在则直接抛出一个InvalidOperationException异常。

路由对象针对GetVirtualPath方法而进行的路由匹配只要求URL模板中定义的变量的值都能被提供,而这些变量值具有三种来源,分别是路由对象定义的默认变量值、指定RequestContext的RouteData提供的变量值(Values属性)和手工提供的变量值(通过values参数指定的RouteValueDictionary对象),这三种变量值的选择优先级由低到高。同样以之前定义关于获取天气信息的URL模板为例,下面是路由注册代码。

   1: public class Global : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start(object sender, EventArgs e)
   4:     {
   5:         var defaults = new RouteValueDictionary { { "areacode", "010" }, { "days", 2 }};
   6:         var constaints = new RouteValueDictionary { { "areacode", @"0\d{2,3}" }, { "days", @"[1-3]{1}" } };
   7:         var dataTokens = new RouteValueDictionary { { "defaultCity", "BeiJing" }, { "defaultDays", 2 } };
   8:         RouteTable.Routes.MapPageRoute("default", "{areacode}/{days}", "~/weather.aspx", false, defaults, constaints, dataTokens);
   9:     }
  10: }

我们在Weather.aspx页面的后台代码中通过如果如下的代码调用RouteTable和Routes熟悉的GetVirtualPath方法生成三个具体的URL。

   1: public partial class Weather : Page
   2: {
   3:     protected void Page_Load(object sender, EventArgs e)
   4:     {
   5:         RouteData routeData = new RouteData();
   6:         routeData.Values.Add("areaCode","0512");
   7:         routeData.Values.Add("days","1");
   8:         RequestContext requestContext = new RequestContext();
   9:         requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current);
  10:         requestContext.RouteData = routeData;
  11:  
  12:         RouteValueDictionary values = new RouteValueDictionary();
  13:         values.Add("areaCode", "028");
  14:         values.Add("days", "3");
  15:  
  16:         Response.Write(RouteTable.Routes.GetVirtualPath(null,null).VirtualPath + "<br/>");
  17:         Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, null).VirtualPath + "<br/>");
  18:         Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, values).VirtualPath + "<br/>");
  19:     }
  20: }

从上面的代码片断我们可以看到:第一次调用GetVirtualPath方法传输的requestContext和values参数均为Null;第二次则指定了一个手工创建的RequestContext对象,其RouteData的Values属性具有两个变量(areaCode=0512;days=1),而values参数依然为Null;第三次我们同时为参数requestContext和values指定了具体的对象,而后者包含两个参数(areaCode=028;days=3)。在浏览器上访问Weather.aspx页面会得到如下图所示的3个URL。这充分证实了上面提到的关于变量选择优先级的结论。

ASP.NET的路由系统:URL与物理文件的分离 ASP.NET的路由系统:路由映射 ASP.NET的路由系统:根据路由规则生成URL

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏林德熙的博客

C#判断文件是否被混淆

可以使用混淆工具对一个DLL 和 exe 进行混淆。 但是如何知道一个文件是否已经混淆了。 在发布之前,需要知道是不是有文件忘了混淆。

1902
来自专栏大内老A

[WCF REST] WebHttpBinding与消息编码

不论是我们采用SOAP还是REST架构风格,运行时框架体系依然不曾改变,终结点也仍旧是通信的核心。在Web HTTP编程模型中,我们采用基于WebHttpBin...

2136
来自专栏逸鹏说道

.NET中的异步编程下

2、Task类 Task类是封装的一个任务类,内部使用的是ThreadPool类,提供了内建机制,让你知道什么时候异步完成以及如何获取异步执行的结果,并且还能取...

2939
来自专栏葡萄城控件技术团队

程序员Web面试之JSON

JSON是什么? JSON(JavaScript对象表示法), 是在网络通信下,常用的一种数据表达格式,它有助于我们于一个自描述的,独立的和轻的方式呈现并交换数...

22310
来自专栏跟着阿笨一起玩NET

事件(Event)

事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发事件的对象称为事件发送方。捕获...

812
来自专栏大内老A

WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)

[爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道《天天山海经》为此录制的节目视频(苏州话)]]通过上篇的介绍,我们知道了WCF所有与编码与...

2229
来自专栏前端达人

用Async解决回调问题

第一次接触编程时,我们就知道了一块代码是从头执行到尾的。 这就是所谓的同步编程:每个操作完成之后,后面的才会继续。 对于不花计算机太多时间的操作,比如数字相加、...

1154
来自专栏草根专栏

用ASP.NET Core 2.1 建立规范的 REST API -- 翻页/排序/过滤等

本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblog...

1271
来自专栏吴伟祥

手写tomcat监控工具---宕机重启 原

2583
来自专栏林德熙的博客

UWP IRandomAccessStream 与 Stream 互转

本文告诉大家如何将 IRandomAccessStream 和 Stream 互转

1382

扫码关注云+社区