ASP.NET MVC路由匹配检测组件RouteDebug.dll

本文介绍了一种名为RouteDebug的工具,用于ASP.NET MVC项目的路由检测。该工具可以帮助开发者了解URL路径如何映射到项目中的路由规则,并展示了如何在项目中配置及使用此工具。

以前我们使用RouteMonitor.dll进行MVC路由检测URL路径的映射匹配情况。由于公司电脑没有此组件,所以上网搜了下,结果才发现RouteMonitor.dll已经将名称改为了RouteDebug.dll 。

  具体参阅 官方网站

  下载地址:http://files.cnblogs.com/Capricornus/RouteDebug-Binary.zip

  使用方法:

  1. 在MVC项目中添加引用此组件

  2. 在全局应用程序类Global.asax.cs中设置代码  

  
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

// 以前RouteMonitor方式
// RouteMonitor.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
}

3.匹配路由如下图:  


   我们可以使用Reflector反编译这个RouteDebugger.dll组件,查看一下原理。如图:

  RouteDebug中包含了DebugHttpHandler、DebugRoute、DebugRouteHandler、RouteDebugger这4个类。

  首先从我们调用RouteDebug.RouteDebugger.RewriteRoutesForTesting的着手。


   RouteDebugger类:

  
public static class RouteDebugger
{
// Methods
public static void RewriteRoutesForTesting(RouteCollection routes)
{
using (routes.GetReadLock())
{
bool flag = false ;
foreach (RouteBase base2 in routes)
{
Route route
= base2 as Route;
if (route != null )
{
route.RouteHandler
= new DebugRouteHandler();
}
if (route == DebugRoute.Singleton)
{
flag
= true ;
}
}
if ( ! flag)
{
routes.Add(DebugRoute.Singleton);
}
}
}
}

  首先,整个代码是使用System.Web.Routing命名空间下的RouteCollection.GetReadLock()锁定的,提供一个对象,用于管理在从集合中检索对象时的线程安全性;然后遍历我们传过来的路由集合参数。用RouteDebug中的DebugRouteHandler去替换原有RouteHandler,以便改变Http处理程序的方向,接着将Singletion属性的值添加到路由结合中。


   DebugRoute类:

  
public class DebugRoute : Route
{
private static DebugRoute singleton = new DebugRoute();

private DebugRoute() : base ( " {*catchall} " , new DebugRouteHandler())
{
}

public static DebugRoute Singleton
{
get
{
return singleton;
}
}
}

   DebugRoute继承与Route类,构造函数实现了构造可捕获所有URL地址的Route。


   DebugRouteHandler路由处理程序类:

  
public class DebugRouteHandler : IRouteHandler
{
// Methods
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
DebugHttpHandler handler
= new DebugHttpHandler();
handler.RequestContext
= requestContext;
return handler;
}
}

   实现IHttpHanlder接口的实例化对象,传入了一个RequestContext对象实例。


  DebugHttpHandler类:

  
public class DebugHttpHandler : IHttpHandler
{
[CompilerGenerated]
private RequestContext < RequestContext > k__BackingField;

private static string FormatRouteValueDictionary(RouteValueDictionary values)
{
if ((values == null ) || (values.Count == 0 ))
{
return " (null) " ;
}
string str = string .Empty;
foreach ( string str2 in values.Keys)
{
str
= str + string .Format( " {0} = {1}, " , str2, values[str2]);
}
if (str.EndsWith( " , " ))
{
str
= str.Substring( 0 , str.Length - 2 );
}
return str;
}

public void ProcessRequest(HttpContext context)
{
string str = string .Empty;
if (context.Request.QueryString.Count > 0 )
{
RouteValueDictionary dictionary
= new RouteValueDictionary();
foreach ( string str2 in context.Request.QueryString.Keys)
{
dictionary.Add(str2, context.Request.QueryString[str2]);
}
VirtualPathData virtualPath
= RouteTable.Routes.GetVirtualPath
(
this .RequestContext, dictionary);
if (virtualPath != null )
{
str
= " <p><label>Generated URL</label>: " ;
str
= str + " <strong style=/ " color: #00a;/ " > "
+ virtualPath.VirtualPath + " </strong> " ;
Route route
= virtualPath.Route as Route;
if (route != null )
{
str
= str + " using the route / "" + route.Url + " / " </p> " ;
}
}
}
string format = " <html>/r/n<head>/r/n
<title>Route Tester</title>/r/n <style>/r/n
body, td, th {{font-family: verdana; font-size: small;}}/r/n
.message {{font-size: .9em;}}/r/n
caption {{font-weight: bold;}}/r/n
tr.header {{background-color: #ffc;}}/r/n
label {{font-weight: bold; font-size: 1.1em;}}/r/n
.false {{color: #c00;}}/r/n
.true {{color: #0c0;}}/r/n
</style>/r/n</head>/r/n<body>/r/n<h1>Route Tester</h1>/r/n<div id=/
" main/ " >/r/n
<p class=/
" message/ " >/r/n
Type in a url in the address bar to see which defined routes match it. /r/n
A {{*catchall}} route is added to the list of routes automatically in /r/n
case none of your routes match./r/n </p>/r/n <p class=/
" message/ " >/r/n
To generate URLs using routing, supply route values via the query string. example:
<code>http://localhost:14230/?id=123</code>/r/n </p>/r/n
<p><label>Matched Route</label>: {1}</p>/r/n {5}/r/n
<div style=/
" float : left;/ " >/r/n
<table border=/
" 1 / " cellpadding=/ " 3 / " cellspacing=/ " 0 / " width=/ " 300 / " >/r/n
<caption>Route Data</caption>/r/n
<tr class=/
" header/ " ><th>Key</th><th>Value</th></tr>/r/n
{0}/r/n </table>/r/n </div>/r/n <div style=/
" float : left; margin - left: 10px;/ " >/r/n
<table border=/
" 1 / " cellpadding=/ " 3 / " cellspacing=/ " 0 / " width=/ " 300 / " >/r/n
<caption>Data Tokens</caption>/r/n
<tr class=/
" header/ " ><th>Key</th><th>Value</th></tr>/r/n
{4}/r/n </table>/r/n </div>/r/n <hr style=/
" clear: both;/ " />/r/n
<table border=/
" 1 / " cellpadding=/ " 3 / " cellspacing=/ " 0 / " >/r/n
<caption>All Routes</caption>/r/n <tr class=/
" header/ " >/r/n
<th>Matches Current Request</th>/r/n <th>Url</th>/r/n
<th>Defaults</th>/r/n <th>Constraints</th>/r/n
<th>DataTokens</th>/r/n </tr>/r/n {2}/r/n
</table>/r/n <hr />/r/n <h3>Current Request Info</h3>/r/n
<p>/r/n
AppRelativeCurrentExecutionFilePath is the portion of the request that Routing
acts on./r/n </p>/r/n
<p><strong>AppRelativeCurrentExecutionFilePath</strong>: {3}</p>/r/n</div>/r/n
</body>/r/n</html>
" ;
string str4 = string .Empty;
// RouteData类包含所请求路由的相关值
RouteData routeData = this .RequestContext.RouteData;
// 获得路由的URL参数值和默认值的集合
RouteValueDictionary values = routeData.Values;
// 获取路由的对象
RouteBase base2 = routeData.Route;
string str5 = string .Empty;
using (RouteTable.Routes.GetReadLock())
{
foreach (RouteBase base3 in RouteTable.Routes)
{
// 返回有关集合中与指定值匹配的路由的信息,如果为空,说明不匹配
bool flag = base3.GetRouteData( this .RequestContext.HttpContext) != null ;
string str6 = string .Format( " <span class=/ " { 0 }/ " >{0}</span> " , flag);
string url = " n/a " ;
string str8 = " n/a " ;
string str9 = " n/a " ;
string str10 = " n/a " ;
Route route2
= base3 as Route;
if (route2 != null )
{
// 如果路由不为空,得到匹配的Url路由
url = route2.Url;
// 得到默认的Url匹配规则信息
str8 = FormatRouteValueDictionary(route2.Defaults);
// 得到约束的Url匹配规则信息
str9 = FormatRouteValueDictionary(route2.Constraints);
// 得到命名空间的Url匹配规则信息
str10 = FormatRouteValueDictionary(route2.DataTokens);
}
str5
= str5 + string .Format
(
" <tr><td>{0}</td><td>{1}</td><td>{2}</td>
<td>{3}</td><td>{4}</td></tr>
" ,
new object [] { str6, url, str8, str9, str10 });
}
}
string str11 = " n/a " ;
string str12 = "" ;
// 如果只被{@cacheall}捕获时,提示不匹配
if (base2 is DebugRoute)
{
str11
= " <strong class=/ " false / " >NO MATCH!</strong> " ;
}
else
{
// 匹配的路由信息
foreach ( string str2 in values.Keys)
{
str4
= str4 + string .Format
(
" /t<tr><td>{0}</td><td>{1} </td></tr> " , str2, values[str2]);
}
foreach ( string str2 in routeData.DataTokens.Keys)
{
str12
= str12 + string .Format( " /t<tr><td>{0}</td><td>{1} </td></tr> " ,
 str2, routeData.DataTokens[str2]);
}
Route route3
= base2 as Route;
if (route3 != null )
{
str11
= route3.Url;
}
}
context.Response.Write(
string .Format(format, new object []
{ str4, str11, str5, context.Request.AppRelativeCurrentExecutionFilePath, str12, str }));
}

public bool IsReusable
{
get
{
return true ;
}
}

public RequestContext RequestContext
{
[CompilerGenerated]
get
{
return this . < RequestContext > k__BackingField;
}
[CompilerGenerated]
set
{
this . < RequestContext > k__BackingField = value;
}
}
}

  通过ProcessRequest方法来处理请求,最后呈现在路由检测的页面上。

  首先从RequestContext.RouteData可以得到RouteData类,RouteData类包含所请求路由的相关值。从RouteData.Values获取路由的URL参数值和默认值集合,在从RouteData.Route获取路由的对象,在获取有关集合中与指定值匹配的路由信息.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仿秀达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值