ASP.NET路由容許你在使用URL時沒必要匹配到網站中具體的文件,由於這個URL沒必要匹配到一個文件,你使用了描述用戶行爲且更容易被用戶理解的URL。ios
ASP.NET MVC框架和ASP.NET動態數據(Dynamic Data)擴展路由爲MVC應用和動態數據應用增長了特點。git
在不使用路由的ASP.NET應用中,一個新的請求會被映射到一個物理文件並由該文件處理這個請求,例如一個.aspx文件。例如,以下請求http://server/application/Products.aspx?id=4會題映射到一個包含代碼和標籤來向瀏覽器渲染響應的Products.aspx文件。Web頁面人員使用id=4的查詢字符來肯定顯示的內容。web
使用ASP.NET路由,你能夠定義映射請求-處理程序(request-handler)文件的URL模式,但不必在將這些文件的名字包含在這個URL中。除此以外,你還能夠經過在URL模式中使用佔位符來向請求處理程序傳輸變量數據,而沒必要使用查詢字符串。正則表達式
例如,以下請求 http://server/application/Products/show/beverages,路由分析器會向頁面處理器傳入Products,show,beverages這些值。在這個例子中,若是使用server/application/{area}/{action}/{category}URL模式定義路由,頁面處理器將會收到一個字典集合,這個集合中包含如下鍵值對,area:Products,action:show,category:beverages。若是是在一個不被URL路由管理的請求中,/Products/show/beverages片段將會被看成應用中的一個文件路徑解釋執行。編程
路由是被處理程序映射的URL模式。處理程序能夠是一個物理文件,例如Web Form應用中的.aspx文件。處理也能夠是處理請求的類,例如MVC應用中的控制器。爲了定義一個路由,你須要建立一個Route類的實例來指定URL模式,處理程序和可選的路由名稱。瀏覽器
你須要給RouteTable類的Routes靜態屬性添加Route對象來爲應用添加路由。Routes屬性是一個RouteCollection對象,其中存放着應用中全部路由規則。安全
你一般沒有必要爲MVC應用編寫代碼添加來添加路由規則。Visual Studio的MVC項目模板包含了預配置的URL路由規則。他們定義在MvcApplication類,這個類在Global.asax文件中。服務器
一個URL模式能夠包含字面值(literal)和可變的佔位符(參考URL參數)。這些字面值和佔位符在URL片段中經過斜線(/)字符來分開和定位。網絡
當一個請求到達,這個URL被解析成片段和佔位符,這些變量會提供給請求處理器。這個過程和將數據經過查詢字符串(query strings)中解析和傳輸至請求處理器很相似。這兩種狀況下變量信息都會包含在URL中並傳處處理程序的鍵值對的表單中。對於查詢字符串而言,全部鍵(keys)和值(values)都包含在URL中。對於路由方式,全部鍵就是在URL模式中定義的佔位符名稱,只有值包含中URL中。mvc
在一個URL模式中,你定義的佔位符被大括號包裹起來({and})。你能夠在一個片段中定義多個佔位符,可是它們必須被字面值分隔開。例如,{language}-{country}/{action}就是一個合法的路由模式。然而{language}{country}/{action}不是一個合法的路由模式,由於它們的佔位符之間缺乏字面值或分隔符。所以,路由沒法肯定language和country佔位符的值是何處分隔。
下表給出了合法的路由模式,以及其各自能正確匹配的URL請求。
路由定義 |
匹配URL示例 |
{controller}/{action}/{id} |
/Products/show/beverages |
{table}/Details.aspx |
/Products/Details.aspx |
blog/{action}/{entry} |
/blog/show/123 |
{reporttype}/{year}/{month}/{day} |
/sales/2008/1/5 |
{locale}/{action} |
/US/show |
{language}-{country}/{action} |
/en-US/show |
在MVC應用中,路由標準的URL模式包含{controller}和 {action}佔位符。
當接收到一個請求時,它先被髮送到UrlRoutingModule對象,再發送到MvcHandler HTTP處理程序。MvcHandler HTTP處理程序肯定須要執行的控制器,經過給URL中的controller值添加」Controller」後綴從而肯定將處理本次請求的控制器類型名稱。URL中的action值肯定調用的處理方法。
例如,URL路徑 /Products會被映射成ProductsController控制器。action參數的值是被調用的處理方法的名稱。URL路徑/Products/show的映射結果將會是調用類ProductsController 的方法Show。
下表給出了默認的URL模式和它們能處理的URL請求示例。
默認URL模式 |
匹配URL示例 |
{controller}/{action}/{id} |
http://server/application/Products/show/beverages |
{resource}.axd/{*pathInfo} |
http://server/application/WebResource.axd?d=... |
路由使用模式 {resource}.axd/{*pathInfo} 來阻止對網絡文件的請求,例如WebReource.axd,ScriptResource.axd被傳遞給一個控制器。
對於IIS7.0,能夠不用擴展名。對於IIS6.0,你必須將擴展名.mvc添加到URL模式,以下所示:{controller}.mvc/{action}/{id}
在Web Form應用中,你可使用類RouteCollection的方法MapPageRoute(String, String, String) 建立路由。方法MapPageRoute建立Route對象並將其添加RouteCollection對象中。你須要爲Route對象在參數在指定一些屬性,用來傳給方法MapPageRoute。
一般狀況下,你在方法中添加的路由會被Global.asax文件中Application_Start 方法處理器調用。這種方法確保了這些路由在應用程序啓動時能夠正常調用。它也容許你在爲應用程序作單元測試時可直接調用該方法。當你在作單元測試時若是想要直接調用一個方法,該方法在註冊時就必須是靜態(Visual Basic中Shared)且有一個RouteCollection參數。
下例中演示了Global.asax文件中添加一個Route對象,該對象定義了action和categoryName兩個參數。URL中還定義了一個被定向到名爲Categories.aspx的物理頁面。
protected void Application_Start(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } public static void RegisterRoutes(RouteCollection routes) { routes.MapPageRoute("", "Category/{action}/{categoryName}", "~/categoriespage.aspx"); }
在MVC應用程序中,若是你採用MVC實現控制器的約定,即派生自類ControllerBase且以「Controller」結尾命名,那麼你根本不須要搬運添加路由。預配置的路由將會執行你實現的控制器類中的處理方法。
若是你但願在MVC應用程序中添加自定義的路由,你可使用方法MapRoute(RouteCollection, String, String) 來取代方法MapPageRoute(String, String, String)。
下面示例中演示在Global.asax文件中建立默認MVC路由的代碼,便是Visual Studio中MVC應用程序的項目模板。
public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } }
當你定義一個路由時,你能夠爲參數指定一個默認值。若是一個參數的值不在URL中,則使用默認值。給路由設置默認值時是給類Route的屬性Defaults指定一個字典對象。下例演示瞭如何使用方法MapPageRoute(String, String, String, Boolean, RouteValueDictionary)添加一個包含默認值的路由。
void Application_Start(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); } public static void RegisterRoutes(RouteCollection routes) { routes.MapPageRoute("", "Category/{action}/{categoryName}", "~/categoriespage.aspx", true, new RouteValueDictionary {{"categoryName", "food"}, {"action", "show"}}); }
下圖中演示了ASP.NET路由處理URL請求,路由定義(categoryName的默認值爲food,action默認爲show)和解析結果:
URL |
Parameter values |
/Category |
action = "show" (default value) categoryName = "food" (default value) |
/Category/add |
action = "add" categoryName = "food" (default value) |
/Category/add/beverages |
action = "add" categoryName= "beverages" |
對於MVC應用程序,方法RouteCollectionExtensions.MapRoute的重載版本,如MapRoute(RouteCollection, String, String, Object, Object),容許你指定默認值。
有時候你必須處理包含可變個數的URL片段的URL請求。當你定義一個路由時,你能夠指定當一個URL擁有比模式中還要多的片段時,額外的片段會被看成最後一個片段對待。你須要爲最後一個參數添加一個星號(*)來用這種方式處理額外的片段。這被稱做全匹配(catch-all)參數。包含全匹配參數也將匹配最後參數不帶任何值的URL。下例展現一個能夠匹配沒法肯定片段長度的路由模式。
query/{queryname}/{*queryvalues}
下圖中演示了ASP.NET路由處理URL請求,路由定義和解析結果。
URL |
Parameter values |
/query/select/bikes/onsale |
queryname = "select" queryvalues = "bikes/onsale" |
/query/select/bikes |
queryname = "select" queryvalues = "bikes" |
/query/select |
queryname = "select" queryvalues = Empty string |
路由模式中除了定義了可匹配URL請求的參數個數,還能夠指定這些參數的值須要知足的某些約束。若是一個URL中的參數值不符合一個路由的約束,那麼此路由不會處理該請求。你添加的約束條件是爲了確保URL參數中包含的值能在你的應用程序中工做。
約束條件是用正則表達式或實現了接口IRouteConstraint的對象來定義。當你將一條路由添加進Routes 集合時,你能夠添加包含驗證測試的對象RouteValueDictionary約束條件。字典中的鍵惟一標識符合約束條件的參數。字典中的值既能夠是符合正則表達式的字符串,也能夠是實現接口IRouteConstraint的對象。
若是你提供一個字符串,路由會將它看成符合正則表達式的值,並調用Regex類的IsMatch()方法檢查該參數值是否符合規則。正則表達式老是不區分大小寫檢查。
若是你提供了一個IRouteConstraint對象,ASP.NET路由調用IRouteConstraint對象的Match()方法來檢查參數值是否合法。Match()方法返回布爾值來代表參數值是否合法。
下例中演示如何利用方法MapPageRoute 添加一條路由,併爲參數locale和year添加約束。(MVC應用程序中,使用方法MapRoute。)
public static void RegisterRoutes(RouteCollection routes) { routes.MapPageRoute("", "Category/{action}/{categoryName}", "~/categoriespage.aspx", true, new RouteValueDictionary {{"categoryName", "food"}, {"action", "show"}}, new RouteValueDictionary {{"locale", "[a-z]{2}-[a-z]{2}"},{"year", @"\d{4}"}} ); }
當路由處理URL請求時,例子中路由的定義和解析後的結果以下表所示:
URL |
Result |
/US |
No match. Both locale and year are required. |
/US/08 |
No match. The constraint on year requires 4 digits. |
/US/2008 |
locale = "US" year = "2008" |
在某些狀況下,ASP.NET路由即便可用也不會處理請求。這節將介紹幾種路由不會處理請求的狀況。
默認狀況下,路由不會處理請求時,將其映射到Web服務器上一個已存在的物理文件。例如,若是存在一個物理文件Products/Beverages/Coffee.aspx,路由就不會處理請求http://server/application/Products/Beverages/Coffee.aspx。路由即便以下定義{controller}/{action}/{id},也能匹配該請求,它也不會處理該請求。
若是你但願路由能處理全部請求,即便請求指向一個文件,你能夠經過設置對象RouteCollection的屬性RouteExistingFiles爲true來重寫默認行爲。當你將這個值設置爲true則全部與定義路由模式匹配的請求都會被路由處理。
你也能夠指明路由不處理某些URL請求。定義一個路由並指明由類StopRoutingHandler處理該模式,以阻止路由處理某些請求。當一個請求被StopRoutingHandler對象處理時,StopRoutingHandler對象塊會爲請求添加一些額外的信息。相反,這個請求會被看成一個ASP.NET頁面、Web服務或是其餘ASP.NET終端處理。你可使用方法RouteCollection.Ignore(MVC應用程序中RouteCollectionExtensions.IgnoreRoute)來建立使用類 StopRoutingHandler的路由。下面演示如何阻止對WebResource.axd文件的請求。
public static void RegisterRoutes(RouteCollection routes) { routes.Ignore("{resource}.axd/{*pathInfo}"); }
URL是如何被路由匹配的[How URLs Are Matched to Routes]
當路由開始處理URL請求時,它爲嘗試着將請求匹配到一條路由規則上。一條路由規則可否匹配URL請求取決與如下條件:
爲了不不合適的路由處理了請求,在定義路由規則時必定要考慮全部這些條件。集合 Routes中Route對象出現的順序也應仔細思考。路由集合中從第一項到最後一項依次嘗試的路由匹配。當有一個匹配成功,再也不對後續路由嘗試匹配。一般,添加路由時應先添加最具體的,最後添加最不明確的規則。
例如你添加了以下路由規則:
路由2毫不會處理請求,由於路由1會最早嘗試匹配,而且與路由2匹配的請求在它上面也老是能夠工做。例如請求http://server/application/products/show/bikes看起來好像和路由2更匹配,可是它會被路由1解析,解析結果以下:
當請求的參數缺乏時,默認值就能起做用。然而,它們可能會匹配到並不是你所願的請求。例如,假如添加以下兩條路由規則:
路由2將絕無處理請求的機會。路由1但願能按月份匹配,而路由2則但願是按年度。可是,路由1中的默認值會讓全部匹配路由2的請求在路由1中也能工做。
你能夠在路由中包含常量來避免這種歧義,例如annual/{report}/{year}和monthly/{report}/{year}/{month}。
若是一個URL不能匹配到在RouteTable集合中的任何一個Route對象,ASP.NET路由將不會處理該請求。
若是你想要建立一個連接到你站點頁面的超連接,你可使用URL模式編程建立符合路由的URL。當你修改了路由模式,URL會自動匹配到新的模式上。
參見:https://msdn.microsoft.com/en-us/library/dd535620.aspx
https://msdn.microsoft.com/en-us/library/dd394711.aspx
ASP.NET中,要讓應用程序支持路由功能,須要添加以下配置:
<configuration> <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <!-- more --> </modules> </system.webServer> </configuration>
當runAllManagedModulesForAllRequests爲true時,以下URLhttp://mysite/myapp/home,即便URL中沒有.aspx,.mvc或者其餘擴展名,該請求也能到達ASP.NET。
然而,IIS7的更新致使沒必要添加配置項runAllManagedModulesForAllRequests,由於它原本就支持ASP.NET路由功能。
若是你的站點運行在IIS7且IIS已更新,你就沒必要設置該配置項爲true。事實上,並不推薦設置它,由於它爲全部請求增長了沒必要要的操做。若是設置該配置爲true,全部請求,包括.htm,.jpg和其餘靜態文件都會經過ASP.NET請求通道。
默認runAllManagedModulesForAllRequests爲false。若是網站配置文件中沒有明確將其設置爲true,而你又在未安裝SP1的Windows 7,不包含必要更新的IIS7中運行你的網站。 結果就是,你會看到路由不會工做的錯誤提示。若是路由中存在一些問題,你能夠試試下面的方法:
受權規則可應用於單獨映射的路由URL或同時映射的路由URL和物理URL。例如,受權規則能夠聲明全部用戶均可以訪問以開頭Category的URL,可是隻有管理員才能訪問Categories.aspx頁面。若是路由URL模式contoso.com/Category/{controller}/{action} 映射到物理地址contoso.com/Categoriespage.aspx,你只能爲路由地址添加受權規則,當用一個路由地址請求過以後,全部用戶都被容許可訪問Categoriespage.aspx。然而,當使用物理地址請求以後,只有管理纔有權限訪問。
默認狀況下,受權規則應用於路由地址和物理地址。
在ASP.NET Web窗體應用程序中,你不該該將站點的安全性全寄託在路由受權規則,由於它們可能留下一些未保護處理的物理地址。
你不能使用路由或web.config文件保證MVC應用程序的安全性。惟一能保證MVC應用安全的作法是給全部控制器應用特性 AuthorizeAttribute ,並在登陸和註冊的方法(action)上應用特性AllowAnonymousAttribute 。
Class |
Description |
Represents a route in a Web Forms or MVC application. |
|
Represents a route in a Dynamic Data application. |
|
Serves as the base class for all classes that represent an ASP.NET route. |
|
Stores the routes for an application. |
|
Provides methods that enable you to manage a collection of routes. |
|
Provides additional methods that enable you to manage a collection of routes in MVC applications. |
|
Contains the values for a requested route. |
|
Contains information about the HTTP request that corresponds to a route. |
|
Provides a way to specify that ASP.NET routing should not handle requests for a URL pattern. |
|
Provides a way to define routes for Web Forms applications. |
|
Provides a way to store route Constraints, Defaults, and DataTokensobjects. |
|
Provides a way to generate URLs from route information. |
ASP.NET路由與URL重寫不一樣。URL重寫方式處理到達的請求時,先修改其URL再將請求發送至Web頁面。例如,一個應用程序中可能使用URL重寫將/Products/Widgets/修改成/Products.aspx?id=4。同時,URL重寫的特色是沒有基於你的模式建立URL的API。使用URL重寫,若是你須要個性URL規則,你不得不手動更新全部相關聯的超連接。
使用ASP.NET路由,在處理到達的請求時URL不會發生變化,由於路由功能可能從URL中提取值。當你須要建立一個URL時,給一個方法傳入參數值就能爲你生成URL。修改URL規則,只須要調整一個地方,你在應用程序中建立的全部連接都會自動使用新規則。