剖析Asp.Net路由系統(tǒng)實(shí)現(xiàn)原理
對于Asp.Net Web Forms應(yīng)用來說,請求的Url都是對應(yīng)一個具體的物理文件(http://xxx.com/default.aspx)。這樣的Url與具體物理文件緊密綁定在一起,帶來了諸多方便的局限:可讀性、SEO優(yōu)化等。為了解決這些局限性,微軟引入了URL路由系統(tǒng)。下面通過一個Demo來剖析一下Asp.Net的路由系統(tǒng)。
創(chuàng)建一個空的WebForm應(yīng)用程序,在Global.asax.cs文件中加入如下代碼:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
//處理匹配的文件
RouteTable.Routes.RouteExistingFiles = true;
//url默認(rèn)值
RouteValueDictionary defaults = new RouteValueDictionary() { { "name", "wuwenmao" }, { "id", "001" } };
//路由約束
RouteValueDictionary constraints = new RouteValueDictionary() { { "name", @"\w{2,10}" }, { "id", @"\d{3}" } };
//與路由相關(guān)的值,但不參與路由是否匹配URL模式
RouteValueDictionary dataTokens = new RouteValueDictionary() { { "defaultName", "wuwenmao" }, { "defaultId", "001" } };
RouteTable.Routes.MapPageRoute("default", "employees/{name}/{id}", "~/Default.aspx", false, defaults, constraints, dataTokens);
}
}
新建名為Default的WebForm頁面,頁面代碼如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication2.Default" %>
<!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">
<h1>這是Default.aspx頁面</h1>
<div>
RouteData中Values:
<ul>
<% foreach (var value in RouteData.Values)
{ %>
<li>
<%=value.Key %>=<%=value.Value %>
</li>
<%} %>
</ul>
RouteData中DataTokens:
<ul>
<% foreach (var value in RouteData.DataTokens)
{ %>
<li>
<%=value.Key %>=<%=value.Value %>
</li>
<%} %>
</ul>
</div>
</form>
</body>
</html>
輸入路徑為一下三種,得到的結(jié)果都是一樣的:
http://localhost:2947/employees/wuwenmao/001
http://localhost:2947/employees/wuwenmao
http://localhost:2947/employees/

原因是因?yàn)樽月酚傻臅r候,為路由模板中的變量設(shè)置了默認(rèn)值,所以當(dāng)用以上三種url時是等效的。
回頭看Global文件中,在注冊路由時還設(shè)置了一個變量:

這是使用正則規(guī)則限定了路由模板中變量的值,請求url中對應(yīng)的變量值只有與正則匹配才能正確請求,否則返回404錯誤。如id值長度大于3時:

上面通過一個簡單的例子體驗(yàn)了一下Asp.Net路由系統(tǒng),下面我們通過翻看源碼來剖析一下Asp.Net路由系統(tǒng)的實(shí)現(xiàn)原理。
首先,我們Global文件中使用以下語句注冊一個路由時,實(shí)際上是向全局路由表添加一個路由。

通過Reflector工具,我們可以看到:

現(xiàn)在有個問題,在注冊好路由之后,Asp.Net是如何使用路由系統(tǒng)的呢?實(shí)際上,Asp.Net路由系統(tǒng)是通過注冊一個HttpModule對象,由這個HttpModule對象實(shí)現(xiàn)針對請求進(jìn)行攔截,然后動態(tài)映射到用于處理當(dāng)前請求的HttpHandler對象中,最后通過HttpHandler對象對請求進(jìn)行處理并響應(yīng)。這個HttpModule實(shí)際上就是UrlRoutingModule,我們在啟動Asp.Net程序時,通過Global文件中的Modules屬性可以驗(yàn)證,從下面截圖可以看到,Modules屬性中包含了已經(jīng)注冊的HttpModule,其中就包含UrlRoutingModule:

在這個UrlRoutingModule里面,又進(jìn)行了哪些跟路由相關(guān)的操作呢,我們還是繼續(xù)翻看源碼:


通過上面的源碼查看,我們可以看出,當(dāng)有請求來到時,Asp.Net通過注冊的UrlRoutingModule模塊攔截了請求,然后從全局路由表中查找匹配的RouteData,如果找得到,根據(jù)HttpApplication獲取到對應(yīng)的HttpHandler,然后將其映射到當(dāng)前請求上下文中,供后續(xù)的管道事件用以處理當(dāng)前請求。
下面我們繼續(xù)翻看源碼,剖析一下UrlRoutingModule是怎么從全局路由表中獲取RouteData的:
從上面可以看到,UrlRoutingModule中調(diào)用全局路由表的GetRouteData,實(shí)際上是依次調(diào)用注冊的每個Route的GetRouteData,返回第一個匹配的RouteData,如果注冊的路由都不匹配,返回null。
下面我們再來看看Route里面的GetRouteData做了些什么:
Match方法:


通過依次調(diào)用Route的GetRouteData方法,在GetRouteData方法中做了如下操作:
1、調(diào)用了ParsedRoute類型的Match方法進(jìn)行請求Url和注冊在當(dāng)前Route對象中的路由模板的匹配工作,如果沒有匹配,直接返回null;
2、如果請求Url和當(dāng)前Route對象的路由模板匹配了,常見RouteData對象;
3、根據(jù)注冊路由信息時定義的約束條件來檢驗(yàn)當(dāng)前請求Url是否通過,不通過返回null;
4、為RouteData對象的Values和DataTokens賦值操作;
5、返回RouteData對象;
到此,Asp.Net的路由系統(tǒng)基本上剖析完畢,還有很多細(xì)節(jié)限于篇幅沒辦法一一剖析。
總結(jié):
通過以上的剖析,我們整理一下思路,對Asp.Net路由系統(tǒng)所做的工作做個總結(jié):首先,我們在Global中注冊了Route對象,然后通過在Asp.Net注冊的HttpModule模塊UrlRoutingModule進(jìn)行攔截請求Url,之后從全局路由表RouteTables.Routes中依次調(diào)用Route對象的GetRouteData進(jìn)行請求Url和注冊路由信息的匹配,返回第一個匹配的RouteData,查找完整個RouteTables.Routes后沒有匹配到,返回null,最終會返回404給前端頁面。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
asp.net GridView排序簡單實(shí)現(xiàn)
使用javascript操作table排序才是實(shí)用的排序,這樣排序不怎么好,但是有時候可能會用來,記錄一下。2009-12-12
使用vs2019加.net core 對WeiApi的創(chuàng)建過程詳解
這篇文章主要介紹了使用vs2019加.net core 對WeiApi的創(chuàng)建,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
asp.net 通過httpModule計(jì)算頁面的執(zhí)行時間
有時候我們想檢測一下網(wǎng)頁的執(zhí)行效率。記錄下開始請求時的時間和頁面執(zhí)行完畢后的時間點(diǎn),這段時間差就是頁面的執(zhí)行時間了。要實(shí)現(xiàn)這個功能,通過HttpModule來實(shí)現(xiàn)是最方便而且準(zhǔn)確的。2011-02-02
HTTP協(xié)議下用Web Service上傳大文件的解決方案
HTTP協(xié)議下用Web Service上傳大文件的解決方案...2007-04-04
ASP.NET 使用application與session對象寫的簡單聊天室程序
寫了快一年的asp.net,application對象還真沒怎么用過??戳丝磿?,根據(jù)這兩個對象的特性寫了一個簡單的聊天室程序。真的是非常的簡陋2014-07-07
ASP.NET 2.0 中收集的小功能點(diǎn)(轉(zhuǎn))
ASP.NET 2.0 中收集的小功能點(diǎn)(轉(zhuǎn))...2006-12-12
NET Core 3.0 AutoFac內(nèi)置DI替換的新姿勢分享
這篇文章主要給大家介紹了關(guān)于NET Core 3.0 AutoFac內(nèi)置DI替換的新姿勢,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用NET Core 3.0具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
ASP.NET MVC 項(xiàng)目直接預(yù)覽PDF文件
本文主要介紹了ASP.NET MVC項(xiàng)目實(shí)現(xiàn)直接預(yù)覽PDF文件的方法,具有很好的參考價值,下面跟著小編一起來看下吧2017-02-02
解決 The Controls collection cannot be modified because the co
在.aspx或.ascx的如果包括%,并在.aspx, .ascs中使用了AjaxToolkit中的控件,那么很可能會引發(fā)這個問題,下面給出具體的解決方法。2010-10-10

