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(); } } }

 运行效果:

相关文章
相关标签/搜索