ASP.NET查找路由表RouteTable中路由名等信息的方法
2015-08-18 21:40
861 查看
10年前使用的.NET 2.0需要升级了,要读读.NET Framework 4.5方面的技术书了。最近在看《精通ASP.NET 4.5》(第5版)中有关的路由技术时,发现列出路由表中映射的虚拟路径比较容易,但要找出映射的物理文件路径和路由名就比较麻烦。看到该书后面章节时,找到了路由表映射的物理文件文件路径。于是,使用Bing满世界查找,终于在一个论坛中找到了一个可行的方法。
方法思路是:RouteTable.Routes的类型是RouteCollection,该类派生自Collection<RouteBase>,其中包含了一个不公开的Dictionary<string, RouteBase>字典成员,该字典就是一个路由名作为Key的路由字典。如何获得该字典成员是问题的关键。解决方法是:该字典成员使用了私有字段_namedMap(不知道原文作者是如何知道的,见本文的后记),通过反射技术可以获得字段成员。
1、路由配置(测试用)
下面的代码是一个路由表的设置情况,为简单见,把配置代码写在了全局应用程序类Global的隐藏代码文件Global.asax.cs中。
下面代码是ListRouteItems.aspx的网页部分代码。
下面代码是ListRouteItems.aspx的代码隐藏文件ListRouteItems.aspx.cs,其中包含了获得Dictionary<string, RouteBase>的代码和自定义结构体RouteItem。代码中可以看出,RouteCollection类的_namedMap私有字段保存了路由表字典(基本信息)。
下图是网页程序运行情况。
结合上面网页图和代码ListRouteItems.aspx.cs知道,路由表中路由名null和""空串相同,且没有保存在RouteCollection的_nameMap字典中。
后记
仔细思考了为何原文作者知道RouteCollection有一个_namedMap字段的问题。进一步,即如何破解MS中类型定义未公开的秘密?答案是使用反射技术。例如如下代码就可以大致了解RouteCollection的字段成员,进而估计出该类有一个Dictionary<string, RouteBase>字典成员。
方法思路是:RouteTable.Routes的类型是RouteCollection,该类派生自Collection<RouteBase>,其中包含了一个不公开的Dictionary<string, RouteBase>字典成员,该字典就是一个路由名作为Key的路由字典。如何获得该字典成员是问题的关键。解决方法是:该字典成员使用了私有字段_namedMap(不知道原文作者是如何知道的,见本文的后记),通过反射技术可以获得字段成员。
1、路由配置(测试用)
下面的代码是一个路由表的设置情况,为简单见,把配置代码写在了全局应用程序类Global的隐藏代码文件Global.asax.cs中。
using System; using System.Web.Routing; namespace Test { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { RouteTable.Routes.MapPageRoute(null, "null", "~/null.aspx"); RouteTable.Routes.MapPageRoute("", "empty", "~/empty.aspx"); RouteTable.Routes.MapPageRoute("test", "test", "~/test.aspx"); } } }2、列表路由信息的网页部分(aspx部分)
下面代码是ListRouteItems.aspx的网页部分代码。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ListRouteItems.aspx.cs" Inherits="Test.ListRouteItems" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <form id="form1" runat="server"> <table border="1"> <tr> <td>Name</td> <td>MappedPath</td> <td>PhysicalPath</td> </tr> <asp:Repeater ID="RouteTable" ItemType="Test.RouteItem" SelectMethod="GetRouteItems" runat="server"> <ItemTemplate> <tr> <td><%# Item.Name %></td> <td><%# Item.MappedPath %></td> <td><%# Item.PhysicalPath %></td> </tr> </ItemTemplate> </asp:Repeater> </table> </form> </body> </html>3、列出路由名等信息的程序(aspx.cs部分)
下面代码是ListRouteItems.aspx的代码隐藏文件ListRouteItems.aspx.cs,其中包含了获得Dictionary<string, RouteBase>的代码和自定义结构体RouteItem。代码中可以看出,RouteCollection类的_namedMap私有字段保存了路由表字典(基本信息)。
using System.Collections.Generic; using System.Web.Routing; using System.Reflection; namespace Test { public partial class ListRouteItems : System.Web.UI.Page { public IEnumerable<RouteItem> GetRouteItems() { var routeCollection = GetRouteCollection(); // 获得路由名为Key的字典 foreach (var route in System.Web.Routing.RouteTable.Routes) { Route r = route as Route; if (r != null) { string name = GetRouteName(routeCollection, route); // 获得路由名 PageRouteHandler p = r.RouteHandler as PageRouteHandler; // 获得映射的物理文件路径 yield return new RouteItem { Name = name, MappedPath = r.Url, PhysicalPath = p.VirtualPath }; } } } private Dictionary<string, RouteBase> GetRouteCollection() { var routes = System.Web.Routing.RouteTable.Routes; var namedMapField = routes.GetType().GetField("_namedMap", BindingFlags.NonPublic | BindingFlags.Instance); var collection = namedMapField.GetValue(routes) as Dictionary<string, RouteBase>; return collection; } private string GetRouteName(Dictionary<string, RouteBase> collection, RouteBase route) { foreach (var item in collection) { if (item.Value == route) { return item.Key; } } return "(null)"; } } public struct RouteItem { public string Name { get; set; } public string MappedPath { get; set; } public string PhysicalPath { get; set; } } }4、ListRouteItems.aspx运行图
下图是网页程序运行情况。
结合上面网页图和代码ListRouteItems.aspx.cs知道,路由表中路由名null和""空串相同,且没有保存在RouteCollection的_nameMap字典中。
后记
仔细思考了为何原文作者知道RouteCollection有一个_namedMap字段的问题。进一步,即如何破解MS中类型定义未公开的秘密?答案是使用反射技术。例如如下代码就可以大致了解RouteCollection的字段成员,进而估计出该类有一个Dictionary<string, RouteBase>字典成员。
Type type = typeof(System.Web.Routing.RouteCollection); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (var fi in fields) { Console.WriteLine(fi.Name + "," + fi.FieldType.UnderlyingSystemType); }
相关文章推荐
- ASP.NET文件上传和下载
- [Asp.net]缓存之页面缓存,控件缓存,缓存依赖
- 通用SQL存储过程分页以及asp.net后台调用
- ASP.NET mvc异常处理的方法
- asp.net MVC helper 和自定义函数@functions小结
- asp.net中获得客户端的IP地址
- ASP.net中TextBoxLabel等控件渲染的不同状态
- 如何让Asp.net Web Api全局预防Xss攻击
- asp.net+swfupload 多图片批量上传(附源码下载)
- asp.net页面中如何获取Excel表的内容
- ASP入门(十七)-ASP #include
- 通过扩展改善ASP.NET MVC的验证机制[实现篇]
- windows7下的iis配置asp.net本地网站
- Aspose.Words使用教程之插入文档元素(一)【连载】
- 分享阿里云推荐码 IC1L2A,购买服务器可以直接打9折,另附阿里云服务器部署ASP.NET MVC5关键教程
- 【.Net码农】asp.net获取当前网址url
- ASP.NET AJAX
- ASP入门(十六)-ASP开发的规范
- WCF和ASP.NET Web API
- Asp.net Session Cookie机制