ASP.NET MVC路由匹配檢測組件RouteDebug.dll

作者: Capricornus  來源: 博客園  發布時間: 2010-08-30 22:27  閱讀: 5479 次  推薦: 3   原文鏈接   [收藏]  
摘要:以前使用RouteMonitor.dll進行MVC路由檢測URL路徑的映射匹配情況,現RouteMonitor.dll已經將名稱改為了RouteDebug.dll,本文將講述RouteDebug.dll的使用方法

  以前我們使用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獲取路由的對象,在獲取有關集合中與指定值匹配的路由信息.

3
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()