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中。

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查找路由表RouteTable中路由名等信息的方法相关推荐

  1. linux查看vmware的版本,linux中查看系统版本信息的方法

    前言 测试环境:测试环境: centos7.2 64位 测试用户:root 查看系统位数(32位或64位) 方法1: [root@VM_0_13_centos ~]# uname -a Linux V ...

  2. php 获取照片信息,PHP中读取照片exif信息的方法

    这篇文章主要介绍了PHP中读取照片exif信息的方法,本文从什么是exif信息开始讲解,使用PHP需要什么扩展.及它的安装方法和使用代码示例等,需要的朋友可以参考下 先来了解什么是图片的Exif信息 ...

  3. Java笔记-通过放射获取类中成员名及调用get方法及map构造JSON数据

    目录 通过反射获取类中成员名 通过反射调用get方法 map生成JSON数据 通过反射获取类中成员名 /*** 获取类中的所有成员名* @param currentClass* @return* @t ...

  4. ASP.NET Split(字符文本中的字符太多 解决方法)

    修改原因: Split()里面是用char类型不是string字符串类型 所以只能用一个字符   必须先把多个字符替换成一个字符,然后再分割 1     string    input   = &qu ...

  5. c语言如何读取mp3歌曲信息,VC中读取mp3文件信息的方法

    标准格式的mp3文件中,都有一些自身描述的信息,比如歌曲名称.歌手.专辑名称等信息. 这些信息都记录在mp3文件中,而且格式是固定的.那么,我们就可以用编程的方式来获取这些信息.其实说简单一点,就是V ...

  6. 织梦 详情页 php,织梦dedecms内页、详情页中调用文章发布者信息的方法

    很多人在使用织梦CMS v5.7都遇到了一个关于如何调用文章内容页中的会员信息. 第一.在官方给出的默认模板article_artcile.htm中我们可以看到如下代码: 复制代码代码如下: {ded ...

  7. java微信获取用户信息_SpringBoot中获取微信用户信息的方法

    前言 不知道你是否参加过拼多多上邀请微信好友砍价功能,这个功能实现首先需要考虑的就是获取微信用户的信息.获取用户信息就是获取公众号下微信用户的信息,今天我就来讲讲如何从公众号下获取微信用户信息. 需要 ...

  8. Qt开发中获取系统相关信息的方法,值得收藏参考

    本文转自https://zhuanlan.zhihu.com/p/111005951,这篇写的很详细,但是macos相关的只有一部分太少了,基本都是Windows的,我个人后续也会把相关的系统调用方式 ...

  9. 在ASP.NET MVC应用程序中实现Server.Transfer()类似的功能

    在ASP.NET MVC应用程序中,如果使用Server.Transfer()方法希望将请求转发到其它路径或者Http处理程序进行处理,都会引发"为xxx执行子请求时出错"的Htt ...

最新文章

  1. 【CTF】实验吧 古典密码
  2. neo4j安装_SpringBoot使用Neo4j
  3. 【Time系列三】简单的计时器(秒表)
  4. 为什么Angular的路由执行离不开router-outlet标签
  5. python按行读取文件取消空白行_python去掉空白行的多种实现代码
  6. 常见食物营养成分表图_营养成分表,你会看么?
  7. 机器学习之概念漂移-concept drift
  8. android学习笔记---发送状态栏通知
  9. Kaggle实战之一回归问题
  10. SQL 必知必会·笔记6使用数据处理函数
  11. 2019属猪的男孩起名
  12. Seaborn系列(二):关系绘图
  13. eclipse的web项目中index.jsp文件出现The superclass was not found on the java build path
  14. 电阻(电阻器)学习干货
  15. 数据可视化笔记3 数据可视化基础(几何标记、视觉通道)
  16. 加减法叫做什么运算_加减法四则运算的计算方法是什么
  17. 《*** 法治思想学习纲要》学习辅导
  18. UT源码_105032014126(改)
  19. Lightly:新一代的 Cloud IDE
  20. 海信电视云账号连不上服务器,海信云账号如何使用?图文教程详解

热门文章

  1. iOS开发准备篇-(3)Safari常用快捷键
  2. Python 中 raise 和 raise/from 的区别
  3. 华清远见学习笔记—Level1—Day5—数组和字符串
  4. 企业固定资产管理难点
  5. Isaac-gym(8):Tensor API
  6. 【vivado UG学习】UG906学习笔记:对综合或实现后的结果进行逻辑分析
  7. JAVA程序员装机必备软件攻略
  8. C# 操作word 指定书签位置插入图片并设置图片大小和位置
  9. 美图秀秀2013年6月5日实习生招聘题目
  10. 登录github更改host文件