ASP.NET MVC教程五:ASP.NET MVC中的路由

1、概述

在ASP.NET MVC架構中,控制器在3大核心構件中處於中心地位,經過控制器支配模型和視圖,然而從瀏覽器發出的請求到控制器還須要路由的協助,路由將特定的請求和控制器的動做對應起來。web

在ASP.NET MVC程序中,路由主要有兩方面的職責:正則表達式

  1. 與入站的請求相匹配,將這些請求映射到控制器的動做中。
  2. 構造出站的URL,這些URL能夠響應控制器的動做。

2、路由原理

一、註冊路由

先看Global.asax中的代碼:瀏覽器

網站啓動的時候執行Application_Start方法,經過RouteConfig.RegisterRoutes(RouteTable.Routes)這段代碼進行路由的註冊,在RegisterRoutes上面F12轉到定義,能夠查看該方法,其實就是App_Start文件夾下面的RouteConfig類,該類定義以下:架構

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace ASPNETMVCDemo { /// <summary>
    /// RouteCollection 全部路由的集合 /// </summary>
    public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表示忽略路由 只要URL知足這個正則規則,就不使用路由 // .axd 是由於iis6給沒有後綴的請求加個asd,而後支持MVC的請求
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 默認路由規則 // 裏面使用的是命名參數,順序能夠改變
 routes.MapRoute( // 路由名稱 RouteCollection是個字典 每一個路由都要有本身的名稱,相同名稱的路由會被覆蓋
                name: "Default", // url的正則規則,去掉域名和端口後的地址進行匹配
                url: "{controller}/{action}/{id}", // 默認值
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

註冊路由其實就是把路由規則添加到RouteCollection路由集合中。app

解釋說明:框架

  1. RegisterRoutes方法是在應用程序啓動時(Application_Start)被調用執行的。
  2. RegisterRoutes方法的做用:註冊路由。它的參數是一個集合對象,這個集合對象就是用來保存多項路由數據的。一項路由數據實際上就是某種形式的URL路徑和控制器及其Action的關係,根據這個關係,MVC才能執行到控制器。
  3. 那麼怎麼添加這種路由數據呢?即調用RegisterRoutes方法裏面的routes.MapRoute方法。該方法的第一個參數是路由的名稱,相似於Dictionary字典裏面的key。第二個參數表示的是URL或者是地址。第三個參數是一個匿名類型,表示該路由相關的默認數據,能夠看做一個字典。
  4. 咱們注意到第二個參數其實就是佔位符表示的URL,這個佔位符是用大括號和裏面的字符串表示的。能夠看出裏面不是某種硬編碼的URL地址(這裏的controller表明全部的控制器,而不是某一個具體的控制器。同理,action也是表明全部的方法,而不是某一個具體的action方法),這樣就增長了靈活性,就是用「/」把URL分紅三部分。還有咱們注意到佔位符表示的URL是沒有域名的,這個是容許的,這種匹配是不考慮域名的。
  5. 在ASP.NET MVC中咱們見得最多的是「{controller}/{action}/{id}」這種形式的URL,那麼controller和action這兩個單詞是否有特殊的用途呢,能不能改變這兩個單詞的寫法。答案是不能的。這時由於會把controller、action和id當作字典或集合的key值來存儲對應的URL片斷,這樣框架在處理時,會讀取鍵名爲controller的數據,好比Home,而後獲得要執行的控制器是HomeController。一樣會從字典中讀取鍵名爲action的數據,好比Index,而後獲得要執行的Action方法是Index。若是這兩個單詞寫錯了,就執行不到相應的controller和action方法了。因此必定要記住寫成controller和action是一種約定,其餘參數的定義就沒有這種要求了。可是action和controller的位置能夠修改。

啓動程序,這時URL地址是:http://localhost:49730asp.net

其實該地址至關於在瀏覽器裏面輸入:http://localhost:49730/Home/Index,這時由於在路由規則裏面設置了默認值,若是沒有控制器和action方法,則默認是Home控制器下面的Index方法。網站

修改URL裏面的controller和action,代碼以下:ui

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace ASPNETMVCDemo { /// <summary>
    /// RouteCollection 全部路由的集合 /// </summary>
    public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表示忽略路由 只要URL知足這個正則規則,就不使用路由 // .axd 是由於iis6給沒有後綴的請求加個asd,而後支持MVC的請求
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 默認路由規則 // 裏面使用的是命名參數,順序能夠改變
 routes.MapRoute( // 路由名稱 RouteCollection是個字典 每一個路由都要有本身的名稱,相同名稱的路由會被覆蓋
                name: "Default", // url的正則規則,去掉域名和端口後的地址進行匹配
                url: "{controller1}/{action1}/{id}", // 默認值
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

 而後運行程序查看結果:編碼

這時程序運行出錯,因此說controller和action千萬不能寫錯。把controller和action改回正確的,而後顛倒controller和action的位置,代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace ASPNETMVCDemo { /// <summary>
    /// RouteCollection 全部路由的集合 /// </summary>
    public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // 表示忽略路由 只要URL知足這個正則規則,就不使用路由 // .axd 是由於iis6給沒有後綴的請求加個asd,而後支持MVC的請求
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 默認路由規則 // 裏面使用的是命名參數,順序能夠改變
 routes.MapRoute( // 路由名稱 RouteCollection是個字典 每一個路由都要有本身的名稱,相同名稱的路由會被覆蓋
                name: "Default", // url的正則規則,去掉域名和端口後的地址進行匹配
                url: "{action}/{controller}/{id}", // 默認值
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

 在運行程序查看結果:

這說明:controller和action的位置是能夠顛倒的。這時若是想輸入完整的URL地址就行訪問就應該輸入:http://localhost:49730/Index/Home。

二、路由匹配

2.一、匹配方式一

看下面的截圖:

解釋說明:

  1. {parameter}:花括弧加任意長度的字符串表示模糊匹配,字符串不能定義成controller和action。默認路由規則就是使用模糊匹配,沒有指明具體是哪一個控制器裏面的哪一個action方法。
  2. 字面量即一個常數字符串,這個字符串能夠在大括弧與大括弧之間,也能夠在最前面或最後面。
  3. 兩個大括弧之間沒有任何的字面量是不能夠的。

 看下面的示例:

首先修改Home控制器裏面的Index方法,修改後的代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace ASPNETMVCRoute.Controllers { public class HomeController : Controller { public ActionResult Index() { string paras = ""; // 遍歷獲取參數值
            foreach(KeyValuePair<string,object> keyValue in RouteData.Values) { paras += string.Format($"{keyValue.Key}={keyValue.Value} "); } // 經過ViewData向頁面傳值
            ViewData["msg"] = paras; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

 修改對應的視圖,在界面展現ViewData["msg"]的值:

@{ ViewBag.Title = "Home Page"; } <div class="jumbotron">
        <h1>ASP.NET</h1>
        <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
        <p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
        <!--展現ViewData["msg"]的值-->
        <p style="color:red;">@ViewData["msg"]</p>
    </div>

<div class="row">
    <div class="col-md-4">
        <h2>Getting started</h2>
        <p> ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. </p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Get more libraries</h2>
        <p>NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.</p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Web Hosting</h2>
        <p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more &raquo;</a></p>
    </div>
</div>

 一、使用{parameter}作模糊匹配其實就是默認路由規則:

routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );

 運行程序查看結果:

二、使用字面量作精確匹配

路由規則以下代碼所示:

routes.MapRoute( name: "const", url: "admin/{controller}/{action}" );

 運行程序,在瀏覽器裏面輸入:http://localhost:64957/admin/home/index,運行結果以下:

三、不容許連續的URL參數

路由規則以下:

routes.MapRoute( name: "blx", // 錯誤的URL // url: "{language}{country}/{controller}/{action}"
      url: "{language}-{country}/{controller}/{action}" );

運行程序,URL裏面輸入:http://localhost:64957/chinese-china/home/index,運行結果以下:

2.二、匹配方式二

看下面截圖:

解釋說明:

  1. 使用「*」來匹配URL剩餘的部分,如*plus放在一個表達式的尾部,最後尾部的URL會保存爲plus爲鍵名的字典值。

看下面的路由規則:

routes.MapRoute( name: "RouteRule", url: "{controller}/{action}/{query-name}/{*plus}" );

 運行程序,在URL裏面輸入:http://localhost:64957/home/index/123/wqer_1234,運行結果以下:

2.三、匹配方式三

看下面截圖:

解釋說明:

  1. 在URL表達式中有一種特殊的狀況,就是URL表達式可能和實際的URL有多種匹配狀況,這時候遵照貪婪匹配的原則(即從後往前進行匹配)。

路由規則1:

routes.MapRoute( name: "tlppone", url: "{controller}/{action}/{filename}.{ext}" );

 運行程序,在URL裏面輸入:http://localhost:64957/home/index/2342.234.234.aspx,運行結果以下:

路由規則2:

routes.MapRoute( name: "tlpptwo", url: "{controller}/{action}/{foo}xyz{bar}" );

 運行程序,在URL裏面輸入:http://localhost:64957/home/index/xyzxyzxyzwer23,運行結果以下:

完整路由規則代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace ASPNETMVCRoute { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 使用字面量作精確匹配 // http://localhost:64957/admin/home/index
 routes.MapRoute( name: "const", url: "admin/{controller}/{action}" ); // 不容許連續的URL參數 // http://localhost:64957/chinese-china/home/index
 routes.MapRoute( name: "blx", // 錯誤的URL // url: "{language}{country}/{controller}/{action}"
                  url: "{language}-{country}/{controller}/{action}" ); // 使用*號匹配URL剩餘部分 // http://localhost:64957/home/index/2342.234.234.aspx 與第一個和第二個路由規則都匹配,顯示第一個,說明路由匹配的順序是從上往下 // http://localhost:64957/home/index/123/wqer_1234
 routes.MapRoute( name: "RouteRule", url: "{controller}/{action}/{query-name}/{*plus}" ); // 貪婪匹配 // http://localhost:64957/home/index/2342.234.234.aspx
 routes.MapRoute( name: "tlppone", url: "{controller}/{action}/{filename}.{ext}" ); // 貪婪匹配2 // http://localhost:64957/home/index/xyzxyzxyzwer23
 routes.MapRoute( name: "tlpptwo", url: "{controller}/{action}/{foo}xyz{bar}" ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

三、URL參數默認值

3.一、參數默認值一

看下面的截圖:

解釋說明:

  1. 如上圖所示,咱們使用了參數的默認值,上圖下方的URL都是匹配這個路由的,若是沒有使用默認值,那麼就只能使用http://localhost/home/index/1這種完整形式的URL地址了。

路由規則代碼以下:

// 參數默認值一
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );

3.二、參數默認值二

看下面截圖:

解釋說明:

  1. 首先咱們說的路由項只提供部分URL片斷默認值的狀況,一條規則就是若是在路由項中使用默認值,可是沒有提供所有默認值,那麼沒有提供默認值的必須經過URL提供。在上面截圖中,控制器必須在URL裏面提供。

路由規則以下:

// 參數默認值二:默認值不提供的必須經過URL提供
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { action = "Index", id = UrlParameter.Optional });

 這時直接運行程序,由於沒有提供controller,因此程序會報錯:

而後在URL裏面輸入:http://localhost:55650/Home,就能夠正常訪問了:

3.四、參數默認值三

解釋說明:

  1. 若是隻提供了部分參數,並且提供的部分參數是URL表達式中間的,如上圖所示,這種狀況下action是不起做用的,因此,這種定義默認值的方式是沒有意義的!

路由規則以下:

// 參數默認值三:只提供中間參數的默認值是不起做用的
routes.MapRoute( name: "Default2", url: "{controller}/{action}/{id}", defaults: new { action = "Index" } );

 

這時候須要在瀏覽器裏面輸入完整的URL才能訪問。

3.四、參數默認值四

看下面截圖:

解釋說明:

  1. 最後一種默認值的特殊狀況,就是在URL表達式中使用字面量,注意這個字面量是除-以外的任意字符的組合,那麼字面量相鄰的URL參數的默認值是不起做用的。
  2. 規律:使用/把URL劃分紅若干個部分,若是各個部分包含了URL參數和字面量,那麼給這些URL參數提供默認值是不起做用的。如圖所示,給參數2和參數3是不起做用的!

路由規則以下:

// 參數默認值四:只提供中間參數的默認值是不起做用的
routes.MapRoute( name: "Default2", url: "{controller}-{action}", defaults: new { action = "Index" });

運行程序,若是瀏覽器裏面只輸入http://localhost:55650/home- 是報錯的:

這時須要輸入完整的URL地址:http://localhost:55650/home-index

四、參數值約束

 假如咱們想對URL後面的數字進行限制,好比四位數字或者兩位數字,以下圖所示,該如何限制呢?

一、使用正則表達式

以下圖所示:

解釋說明:

  1. 在MVC的路由中咱們能夠對URL的各個參數定義約束,有兩種約束方法,第一種是使用正則表達式,如上圖所示。
  2. MapRoute提供了一個重載方法,就是在默認值後面增長了一個約束的參數,這個參數可使用匿名類型設置值,在匿名類裏面能夠設置各類參數對應的正則表達式,如上圖所示。

路由規則以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCURLParaConstraint { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 一、使用正則表達式設置參數值的約束
 routes.MapRoute( name: "Default1", url: "{controller}/{action}/{id}/{year}/{month}/{day}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // year是4位整數 month和day是2位整數
              constraints:new { year = @"\d{4}",month=@"\d{2}",day=@"\d{2}"} ); // 默認路由
 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

 運行程序,在瀏覽器裏面輸入:http://localhost:51244/Home/Index/1/2019/05/24,效果以下:

由於設置了約束month是2位整數,這時將month改成1位整數,而後輸入:http://localhost:51244/Home/Index/1/2019/5/24,效果以下:

這時程序就報錯了,說明設置的正則約束起做用了。

二、使用約束類

以下圖所示:

解釋說明:

  1. 在有些時候,若是約束規則很複雜或者正則表達式很難寫,或者你根本就不擅長寫正則表達式,那麼能夠考慮第二種約束方式:約束類。
  2. 如上圖所示:定義約束類就是要實現IRouteConstraint接口的Match方法,這個方法就是用來判斷接口是否匹配的。使用這個約束類的方法也很簡單,就是在之前使用正則表達式的地方,換成用約束類的實例賦值,如上圖所示。

 路由規則以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCURLParaConstraint { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 二、使用約束類來約束參數值
 routes.MapRoute( name: "Default1", url: "{controller}/{action}/{id}/{year}/{month}/{day}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // 使用約束類的實例
               constraints: new { year = @"\d{4}", month =new MonthConstraint(), day = @"\d{2}" } ); // 一、使用正則表達式設置參數值的約束 //routes.MapRoute( // name: "Default1", // url: "{controller}/{action}/{id}/{year}/{month}/{day}", // defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, //  // year是4位整數 month和day是2位整數 // constraints:new { year = @"\d{4}",month=@"\d{2}",day=@"\d{2}"} // ); // 默認路由
 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } /// <summary>
    /// 對月進行約束,實現IRouteConstraint接口 /// 對年或者日進行約束同理 /// </summary>
    public class MonthConstraint : IRouteConstraint { // 實現Match方法
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { // values["month"]表示根據鍵名或者值 // 長度爲2,而且在1到12之間表示匹配經過返回true,不然不經過返回false
            if (values["month"].ToString().Length==2 && Convert.ToInt32(values["month"])>=1 && Convert.ToInt32(values["month"]) <=12) { return true; } else { return false; } } } }

 運行程序,在瀏覽器裏面輸入:http://localhost:51244/Home/Index/2/2019/05/24 ,效果以下:

五、路由匹配順序

以下圖所示:

解釋說明:

  1. 如圖所示,上面的URL跟哪一個路由規則匹配呢?答案是匹配Default1這個路由,爲何會是這樣呢?其實若是隻註冊單獨的一條路由,這兩條路由規則都是匹配這個URL的,這裏有一個原則:若是有多條路由都和這個URL匹配,那麼就是排在最前面的優先匹配,排在後面的就不在進行匹配。

六、排除路由

解釋說明:

  1. 咱們注意到RigisterRoutes方法中默認的第一句代碼是routes.IgnoreRoute方法,他的做用就是排除路由,好比上圖下面的URL不會在路由表中匹配的,而是直接被忽略掉!

  2. 若是出了.axd之外的文件須要忽略,那麼在IgnoreRoute方法裏面添加須要忽略的路由便可。

五、由URL到控制器

先看下面的截圖:

解釋說明:

  1. 經過前面路由註冊的代碼會最終造成一個路由集合的數據,能夠看做是一個路由表(RouteTable),那麼請求是如何經過URL進入到相應的控制器及Action方法的呢?
  2. 如上圖所示,請求到達ASP.NET MVC應用程序後,首先會通過一個名爲「UrlRoutingModule」的HttpModule,HttpModule能夠過濾每個請求,UrlRoutingModule的做用就是根據請求的URL從路由表中查找和URL匹配的路由,而後從匹配的路由中獲得一個名爲MvcHandler的HttpHandler,以後就執行它的ProcessRequest方法,在ProcessRequest方法的內部找到Controller,並繼續往下執行。
  3. 說到這裏可能有疑問:某項路由數據是怎樣聯繫到一個HttpHandler的呢?以下圖中的源碼所示:MapRoute方法實際上包含這樣一段代碼,在new的時候會初始化一個MvcRouteHandler對象,而後經過MvcRouteHandler的GetHttpHandler方法能夠獲得真正的處理程序MvcHandler。

上面說的UrlRoutingModule在哪裏呢?看下面截圖:

六、從控制器中獲取URL值的方式

從控制器中獲取URL中的值共有三種方式:

解釋說明:

  1. Request.QueryString只能獲取以?分隔的參數值!
  2. RouteDate.Values[「id」]就是當前字典上的路由數據,經過訪問鍵名的方式獲得鍵值,好比URL模式匹配的字符串是id,這裏必須是id。

  3. Action方法的參數和路由字典的參數是對應的,MVC框架在執行action以前會首先爲這些參數賦值。

6.一、Request.QueryString

控制器代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCURlValue.Controllers { public class HomeController : Controller { /// <summary>
        /// Request.QueryString /// </summary>
        /// <returns></returns>
        public ActionResult Index() { if(Request.QueryString["bookid"]!=null) { string value = Request.QueryString["bookid"]; ViewData["msg"] = value; } return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

 

視圖也代碼以下:

@{ ViewBag.Title = "Home Page"; } <div class="jumbotron">
    <h1>ASP.NET</h1>
    <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
    <p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
    <p style="color:red;font-weight:bold;">@ViewData["msg"]</p>
</div>

<div class="row">
    <div class="col-md-4">
        <h2>Getting started</h2>
        <p> ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. </p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Get more libraries</h2>
        <p>NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.</p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more &raquo;</a></p>
    </div>
    <div class="col-md-4">
        <h2>Web Hosting</h2>
        <p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>
        <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more &raquo;</a></p>
    </div>
</div>

程序運行效果:

6.二、RouteData.Values

控制器代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCURlValue.Controllers { public class HomeController : Controller { /// <summary>
        /// Request.QueryString /// </summary>
        /// <returns></returns>
        //public ActionResult Index() //{ // if(Request.QueryString["bookid"]!=null) // { // string value = Request.QueryString["bookid"]; // ViewData["msg"] = value; // } // return View(); //}


        /// <summary>
        /// RouteData.Values /// </summary>
        /// <returns></returns>
        public ActionResult Index() { string value = $"controller={RouteData.Values["controller"]},action={RouteData.Values["action"]}"; ViewData["msg"] = value; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

運行效果:

這時會遇到一個問題,若是在URL裏面還有其餘參數呢?好比下面的狀況

 

這時候若是要獲取id的值就要修改代碼,那麼有沒有其餘簡便的方式呢?看下面代碼:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCURlValue.Controllers { public class HomeController : Controller { /// <summary>
        /// Request.QueryString /// </summary>
        /// <returns></returns>
        //public ActionResult Index() //{ // if(Request.QueryString["bookid"]!=null) // { // string value = Request.QueryString["bookid"]; // ViewData["msg"] = value; // } // return View(); //}


        /// <summary>
        /// RouteData.Values /// </summary>
        /// <returns></returns>
        public ActionResult Index() { // 方式一 //string value = $"controller={RouteData.Values["controller"]},action={RouteData.Values["action"]}"; // 方式二
            string value = ""; foreach(var item in RouteData.Values) { value += $"{item.Key}={item.Value} "; } ViewData["msg"] = value; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

 運行效果:

由於RouteData.Values是一個字典集合,因此能夠遍歷RouteData.Values,這樣不管URL裏面有多少參數,均可以獲取到對應的value值。

6.三、action參數

控制器代碼:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCURlValue.Controllers { public class HomeController : Controller { /// <summary>
        /// Request.QueryString /// </summary>
        /// <returns></returns>
        //public ActionResult Index() //{ // if(Request.QueryString["bookid"]!=null) // { // string value = Request.QueryString["bookid"]; // ViewData["msg"] = value; // } // return View(); //}


        /// <summary>
        /// RouteData.Values /// </summary>
        /// <returns></returns>
        //public ActionResult Index() //{ //    // 方式一 //    //string value = $"controller={RouteData.Values["controller"]},action={RouteData.Values["action"]}"; //    // 方式二 // string value = ""; // foreach(var item in RouteData.Values) // { // value += $"{item.Key}={item.Value} "; // } // ViewData["msg"] = value; // return View(); //}



        /// <summary>
        /// action參數 /// 方法參數名稱必須和URL裏面參數名稱保持一致 /// </summary>
        /// <returns></returns>
        public ActionResult Index(string controller,string action) { string value = $"controller={controller},action={action}"; ViewData["msg"] = value; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

運行效果:

七、由路由到URL

解釋說明:

  1. 1.由路由生成URL其實就是簡單的兩句代碼,第一步就是使用RouteCollection對象的GetVirtualPath方法,經過該方法能夠返回一個VirtualPahData對象,該類型表示有關路由和虛擬路徑的信息,包含了兩個重載的方法,區別是第二個方法能夠指定路由項的名稱,就是添加路由時,設置的路由鍵名,參數Values表達生成URL時設置的參數值,是一個字典類型。

  2. 1.獲得VirtualPahData實例後,就能夠經過他的VirtualPath屬性值獲得URL地址,它是一個字符串類型,從路由的這個功能能夠看出,他是有雙向功能的,不一樣於URL重寫!

看下面的案例:

修改RouteConfig代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCRouteToUrl { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default2", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", id = UrlParameter.Optional } ); // 默認路由匹配規則
 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }

控制器代碼以下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCRouteToUrl.Controllers { public class HomeController : Controller { public ActionResult Index() { // 1.不使用路由名稱的方式生成URL
            VirtualPathData vp= RouteTable.Routes.GetVirtualPath(null, new RouteValueDictionary(new { controller = "Home", action = "Index2", id = 4 })); string url = vp.VirtualPath; ViewData["msg"] = url; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

 界面運行效果:

在看下面一種方式:

控制器代碼:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace MVCRouteToUrl.Controllers { public class HomeController : Controller { public ActionResult Index() { // 1.不使用路由名稱的方式生成URL //VirtualPathData vp= RouteTable.Routes.GetVirtualPath(null, new RouteValueDictionary(new { controller = "Home", action = "Index2", id = 4 })); //string url = vp.VirtualPath; //ViewData["msg"] = url; // 2.根據路由名稱生成URL // 由於controller和id有默認值,因此這裏只指定action的值
            VirtualPathData vp = RouteTable.Routes.GetVirtualPath(null, "Default2", new RouteValueDictionary(new { action = "Index5" })); string url = vp.VirtualPath; ViewData["msg"] = url; return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

 運行效果:

相關文章
相關標籤/搜索