上周我写了三篇文章(一、二、三)详细地介绍了ASP.NET的路由系统。ASP.NET的路由系统旨在通过注册URL模板与物理文件之间的映射进而实现请求地址与文件路径之间的分离,但是对于ASP.NET MVC应用来说,请求的目标不再是一个具体的物理文件,而是定义在某个Controller类型中的Action方法。出于自身路由特点的需要,ASP.NET对ASP.NET的路由系统进行了相应的扩展。
一、基本路由映射
通过前面的介绍我们知道基于某个物理文件的路由映射通过调用代表全局路由表的RouteTable的静态属性Routes(一个RouteCollection对象)的MapPageRoute方法来完成,为了实现针对目标Controller和Action的路由,ASP.NET MVC针对RouteCollection类型定义了一系列的扩展方法以实现文件路径无关的路由映射,这些扩展方法定义在RouteCollectionExtensions类型中。如下面的代码片断所示,RouteCollectionExtensions定义了两组方法,方法IgnoreRoute用于注册不需要进行路由的URL模板,对应于RouteCollectionExtensions的Ignore方法;仿佛MapRoute用于进行基于URL模板的路由注册,对应于RouteCollectionExtensions的MapPageRoute方法。
1: public static class RouteCollectionExtensions 2: { 3: //其他成员 4: public static void IgnoreRoute(this RouteCollection routes, string url); 5: public static void IgnoreRoute(this RouteCollection routes, string url, object constraints); 6: 7: public static Route MapRoute(this RouteCollection routes, string name, string url); 8: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults); 9: public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces); 10: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints); 11: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces); 12: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces); 13: }
由于ASP.NET MVC的路由注册与具体的物理文件无关,所以MapRoute方法中并没有一个表示文件路径的physicalFile参数。与直接定义在RouteCollectionExtensions中的Ignore和MapPageRoute方法不同的是,表示默认变量的参数defaults和基于正则表达式的变量约束的参数constraints都不再是一个RouteValueDictionary对象,而是一个普通的object。这主要是为了编程上的便利,使得我们可以通过匿名类型的方式来指定这两个参数值。该方法在内部会通过反射的方式得到指定对象所有属性值,并转换为RouteValueDictionary对象,其属性名和属性值作为字典元素的Key和Value。
对于ASP.NET MVC来说,最终需要通过在请求地址中指定的Controller名称来创建具体的Controller实例。由于Controller名称 仅仅对应着类型的名称,Controller的成功实例化的前提是我们能够正确地解析出它的具体类型,所以我们需要使用了命名空间。在调用MapRoute方法的时候我们可以通过字符串数组类型的参数namespaces来指定一个命名空间的列表。对于注册的命名空间,可以指定一个代表完整命名空间的字符串,也可以使用“*”作为通配符。
添加的命名控件列表最终是被存储于Route对象的DataTokens属性中,对应的Key为“Namespaces”。MapRoute方法没有为初始化Route对象的DataTokens属性提供相应的参数,如果没有指定命名空间列表,所有通过该方法添加的Route对象的DataTokens属性总是一个空的RouteValueDictionary对象。
对于针对定义在某个Controller中的某个Action的请求,如果注册的路由表与之匹配,具体匹配的某个路由对象的GetRouteData被调用并返回一个具体的RouteData对象。根据对请求地址进行解析得到的目标Controller和Action的名称必须包含在该RouteData的Values属性对应的RouteValueDictionary对象中,其对应的Key分别为controller和action。
二、 实例演示:注册路由映射与查看路由信息
ASP.NET MVC通过定义在RouteCollectionExtensions中的扩展方法MapRoute进行路由映射,为了让读者对此有一个深刻的认识,我们来进行一个简单的实例演示。我们依然沿用之前关于获取天气信息的场景,看看通过这种方式进行注册的Route对象针对匹配的HTTP请求返回怎样的RouteData对象。[源代码从这里下载]
我们在创建的ASP.NET Web应用(不是ASP.NET MVC应用)添加一个Web页面(Default.aspx),并按照之前的方式以内联代码的方式直接将RouteData的相关属性显示出来,页面主体部分的HTML如下所示。需要注意的是我们显示的RouteData是从定义的方法GetRouteData方法获取的,而不是对应于当前页面的RouteData属性。
1: <body> 2: <form id="form1" runat="server"> 3: <div> 4: <table> 5: <tr> 6: <td>Route:</td> 7: <td><%=GetRouteData().Route != null? GetRouteData().Route.GetType().FullName:"" %></td> 8: </tr> 9: <tr> 10: <td>RouteHandler:</td> 11: <td><%=GetRouteData().RouteHandler != null? GetRouteData().RouteHandler.GetType().FullName:"" %></td> 12: </tr> 13: <tr> 14: <td>Values:</td> 15: <td> 16: <ul> 17: <%foreach (var variable in GetRouteData().Values) 18: {%> 19: <li><%=variable.Key%>=<%=variable.Value%></li> 20: <% }%> 21: </ul> 22: </td> 23: </tr> 24: <tr> 25: <td>DataTokens:</td> 26: <td> 27: <ul> 28: <%foreach (var variable in GetRouteData().DataTokens) 29: {%> 30: <li><%=variable.Key%>=<%=variable.Value%></li> 31: <% }%> 32: </ul> 33: </td> 34: </tr> 35: </table> 36: </div> 37: </form> 38: </body>
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, 对象
, 路由
, 方法
, 属性
, URL不能被Routes匹配
, 一个
, Routes
路由实例代码
,以便于您获取更多的相关知识。