文章目录:

   1、认识理解URL,以及简单的路由

   2、特性路由、传统路由、区域路由

   3、路由生成URL&&绑定到操作&&路由约束

1、认识理解URL,以及简单的路由

 默认简单的路由(概述、路由&URL重写)

  先来看下两个名词 URL(统一资源定位符),URI(统一资源标识符)

  高质量URL应该满足的规则:域名便于记忆和拼写、域名简短、便于输入、反映出站点的结构、“可破解的”,用户可以通过移除URL的末尾,进而到达更高层次的信息体系结构,持久不能改变

路由概述:

  asp.net mvc 的路由主要有两种用途 1、匹配传入的请求,并把这些请求映射到控制器操作。2、构造传出的URL,用来响应控制器的操作

路由&URL重写

  它们的共同点是都可以为搜索引擎优化,构建漂亮的URL,不同的是URL重写试讲一个URL映射到另外一个URL,路由关注的是将URL映射到资源;路由使用它的映射规则匹配传入的URL帮助生成URL,URL重写只能用于传入的URL,不能帮助生成原始的URL。

2、特性路由、传统路由、区域路由

特性路由:

  让我们来看下什么是特性路由,首先创建一个MVC项目,来到网站的入口点Global.asax文件,会看到在Application_Start 方法里面,存在一个方法 RouteConfig.RegisterRoutes(RouteTable.Routes);这个方法是集中控制路由的地方,这个方法对应着RouteConfig.cs文件的RegisterRoutes方法,因为我们要测试特性路由,因此我们把代码这样:

public static void RegisterRoutes(RouteCollection routes)
{
//routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); //routes.MapRoute(
// name: "Default",
// url: "{controller}/{action}/{id}",
// defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
//);
routes.MapMvcAttributeRoutes();
}

路由的核心工作是将一个请求映射到一个操作。静态路由,接下来,我们在Home控制器下的About方法上面使用一个特性

[Route("about")]
public ActionResult About()
{
ViewBag.Message = "Your application description page."; return View();
}

那当我们URL为about的时候、特性路由就会运行Home控制器的about方法,如下图所示:

例如我们的首页,想要由多个匹配规则全都能匹配到,这时候就可以如此定义特性路由

[Route("")]
[Route("index")]
[Route("home/index")]
public ActionResult Index()
{
return View();
}

路由值

例如我们现在要根据一个人的Id查询这个人的一些信息,此时Id作为参数传入,我们可以这样定义路由

[Route("person/{id}")]
public ActionResult Details(int id)
{
//Query person
return View();

我们的URL为person/1时候,就会访问到Details方法,参数Id值为1。也就是说当特性路由匹配并运行操作方法时,模型绑定会使用路由的路由参数为同名的方法参数填充值

控制器路由

我们可以使用特殊的路由参数"action"来匹配某个控制器下所有的方法

[Route("home/{action}")]
public class HomeController : Controller
{
//other action
}

我们可以使用RoutePrefix 特性仅在一个地方制定路由开头

[RoutePrefix("home")]
[Route("{action}")]
public class HomeController : Controller
{
[Route("")]
[Route("index")]
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page."; return View();
} public ActionResult Contact()
{
ViewBag.Message = "Your contact page."; return View();
}
}

此时访问URL /index 和 /home/index就会如下结果

加入我们想直接访问Home控制器的Index方法,我们就可以在Index方法上面添加以下特性路由,这样我们的URL 为/,/home,/home/index就都可以访问到Index方法了

[RoutePrefix("home")]
[Route("{action}")]
public class HomeController : Controller
{
[Route("~/")]
[Route("")]
[Route("index")]
public ActionResult Index()
{
return View();
}

路由约束:

例如我们现在控制器里面有两个方法来查找一个人=》

[Route("person/{id}")]
public ActionResult Details(int id)
{
//Query person
return View();
}
[Route("person/{name}")]
public ActionResult Details(string name)
{
//Query person
return View();
}

此时会发现,无论我们的URL 为/person/1 还是/person/bob 都能被[Route("person/{name}")]匹配到,这是我们的特性路由就存在二义性,这时候我们需要给路由添加一个约束,如下图所示,这样/person/1就会被匹配到[Route("person/{id:int}")] 这个路由,这种约束叫做“内联约束”。

[Route("person/{id:int}")]
public ActionResult Details(int id)
{
//Query person
return View();
}
[Route("person/{name}")]
public ActionResult Details(string name)
{
//Query person
return View();
}

 传统路由

接下来我们来看一下传统路由,首先,修改RouteConfig 文件中的RegisterRoutes方法,如下所示

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}");
}

MapRoute方法的第二个参数我们称他为路由模板。路由模板和特性路由相同,是一种匹配规则,目的是将URL链接到操作方法,它们两者的不同点是完成这个操作传统路由依赖于名称字符串,特性路由依赖于特性。

例如现在, 我们的请求URL 为/home/index,根据mvc的约定,mvc 会把Controller 添加到{controller}的参数后面,然后请求{action} 方法。

路由值

我们的路由除了必须的{controller} 和 {action} 参数以外,还可以存在第三个参数,例如下面的代码,我们的RouteConfig方法,我们的路由模板存在{id}这样一个参数,我们称它为路由值,当我们请求URL :/Person/Details/1的时候,该请求会导致MVC实例化PersonController类,调用Details方法,并将1传递给Details方法中的参数Id。

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}/{id}");
}

例如我们想让所有请求都用site/开头,我们就可以这样定义路由模板。

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "site/{controller}/{action}/{id}");
}

路由模板定义非常灵活,但是允许连续定义两个路由参数,例如这样就是错误的:{controller}{action}/{id};

路由默认值:

当我们的路由规则是 {controller}/{action}/{id} 这样的时候,我们要相匹配Person/Index是匹配不到的(因为不存在Id参数),这是我们需要重新定义我们的路由,给MapRoute方法添加第三个参数

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}/{id}"
,new { id=UrlParameter.Optional});
}
new { id=UrlParameter.Optional}这段代码定义了参数{id}的默认值,参数{id}为可选参数,当然我们也可以定义默认的控制器和方法,如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}/{id}"
,new {controller="Home", action = "index", id=UrlParameter.Optional});
}

路由约束:

当我们要请求这样一个控制器方法的时候,就可以使用路由约束。由于路由是从上往下匹配,当我们第一个路由规则匹配成功后,就不再往下匹配,所以,当我们请求URL为/2012/01/01时候,就会被第一个规则匹配到,进入到Home 控制器的Contact方法,当我们请求URL类似/Home/Index/123的时候,就会被第二个路由规则匹配到。

public ActionResult Contact(int year,int month,int day)
{
ViewBag.Message = "Your contact page."; return View();
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("home", "{year}/{month}/{day}"
,new {controller="home", action = "contact", id=UrlParameter.Optional}
,new { year =@"\d{4}", month = @"\d{2}", day= @"\d{2}" });
routes.MapRoute("simple", "{controller}/{action}/{id}");
}

当然我们可以一起使用特性路由和传统路由,如下所示

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes(); //把特性路由放在传统路由的上面,URL优先匹配特性路由
routes.MapRoute("home", "{year}/{month}/{day}"
,new {controller="home", action = "contact", id=UrlParameter.Optional}
,new { year =@"\d{4}", month = @"\d{2}", day= @"\d{2}" });
routes.MapRoute("simple", "{controller}/{action}/{id}");
}

在RouteConfig 的RegisterRoutes方法中,是可以给路由命名的,如下所示,我们使用mvc为我们提供的razor html标签(就是htmlHelper对象。。)的时候可以指定使用那个路由规则进行匹配,如下所示:

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}/{id}"
, new { controller = "Home", action = "index", id = UrlParameter.Optional });
routes.MapRoute("home", "{controller}/{action}/{id}"
, new { controller = "Home", action = "about", id = UrlParameter.Optional });
}
@{
ViewBag.Title = "Index";
} <h2>Index</h2> @Html.RouteLink(
linkText: "route home",
routeName: "home",
routeValues: new { controller = "Home", action = "index", id = })
@Html.RouteLink(
linkText: "route simple",
routeName: "simple",
routeValues: new { controller = "Home", action = "about", id = })

区域路由

mvc2.0 引入区域概念,可以将我们的网站划分为若干个节点,如下所示,我们添加了一个区域,在这个区域中,也存在一个叫做Home的控制器和Index的方法。然后我们访问这个网站,就会这样。。

这个时候,我们需要给项目的路由指定一组用来定位控制器类的名称空间

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("simple", "{controller}/{action}/{id}"
, new { controller = "Home", action = "index" ,id =UrlParameter.Optional}
,new[] { "MVCSummary.Controllers" });
}

catch-all 参数,我们如下定义路由模板,{*extrastuff}被称为catch-all 参数参数,catch-all 参数可以匹配任意段的URL,但是只能作为路由模板的最后一段

public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
routes.MapRoute("simple", "{controller}/{action}/{id}/{*extrastuff}"
, new { controller = "Home", action = "index" ,id =UrlParameter.Optional}
,new[] { "MVCSummary.Controllers" });
}

3、路由生成URL&&绑定到操作&&路由约束

路由除了能匹配传入的请求URL意外,还有一个重要的职责就是生成URL。

路由的核心是RouteCollection基类RouteBase基类。

RouteCollection类有两个重载方法GetVirtualPath,第一个方法传入请求上下文,和用户指定的路由值(一个字典),路由集合通过这个方法遍历每个路由匹配路由模板,假如匹配成功,则返回一个VirtualPathData对象,该对象包含生成的URL实例和用户定义的路由集合,见下图:

第二个GetVirtualPath方法要求传入一个Routename, 它不会挨个遍历路由集合、假如找不到这个名称的路由或者匹配失败,就会返回空值,不再进行匹配。找到这个路由匹配成功则会返回一个VirtualPathData对象。

整个URL的生成如下图所示:

解释个名词,溢出参数:URL生成过程中使用但是没有在路由定义中指定的路由值。 例如我们的请求URL为/Home/Index/1?Page=1 ,这里的Page=1就是溢出参数

接下来让我们看几个Route类生成URL的例子

routes.MapRoute("report",        //这是我们的路由模板
"{year}/{month}/{day}",
new { controller = "Home", action = "Index", day = });
//调用Url.RouteUrl
@Url.RouteUrl(new { param1 = value1, paraml2 = value2,..., paramlN = valueN });
参数 返回URL 说明
year=2017,month=12,day=08 /2017/12/08 直接匹配模板
year=2017,month=12 /2017/12  day默认为10
year=2017,month=12,day=08,Page=10 /2017/12/08?Page=10 Page溢出参数
year=2007 null 参数不足,匹配失败

路由绑定操作&自定义约束

路由是如何绑定到操作的呢,如下图所示:

在ASP.NET MVC中,MvcHandler实现了IHttpHandler接口,用来实例化控制器,并调用控制器上面的方法。

路由数据:RouteCollection的GetRouteData方法会返回一个RouteData实例,这个实例里面包含了匹配请求的路由信息。当外界URL匹配成功时,它就创建一个字典用来保存路由参数,这个字典为Values,例如当路由模板为{controller}/{action}/{id} ,请求URL 为/Home/Index/123 则Values字典中应至少包含三个键controller、action、id,它们的值分别为Home、Index、123;特性路由的字典保存在DataTokens这个字典用。

自定义约束:


路由提供了一个接口IRouteConstraint ,这个接口有一个Math方法,当路由匹配完模板之后,假如有约束实现了IRouteConstraint接口,就会导致路由引擎调用Math方法,来确定是否满足给定请求。

例如我们想要一个只实现Get请求的路由,HttpMethodConstraint继承自IRouteConstraint接口。

 routes.MapRoute("getmap", "{controller}", null, new { httpmethod = new HttpMethodConstraint("Get") });

初探MVC路由的更多相关文章

  1. ASP.NET MVC 路由(一)

    ASP.NET MVC路由(一) 前言 从这一章开始,我们即将进入MVC的世界,在学习MVC的过程中在网上搜索了一下,资料还是蛮多的,只不过对于我这样的初学者来看还是有点难度,自己就想看到有一篇引导性 ...

  2. ASP.NET MVC 路由(二)

     ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...

  3. ASP.NET MVC 路由(三)

    ASP.NET MVC路由(三) 前言 通过前两篇的学习会对路由系统会有一个初步的了解,并且对路由系统中的Url规则有个简单的了解,在大家的脑海中也有个印象了,那么路由系统在ASP.NETMVC中所处 ...

  4. ASP.NET MVC 路由(四)

    ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...

  5. ASP.NET MVC 路由(五)

    ASP.NET MVC 路由(五) 前言 前面的篇幅讲解了MVC中的路由系统,只是大概的一个实现流程,让大家更清晰路由系统在MVC中所做的以及所在的位置,通过模糊的概念描述.思维导图没法让您看到路由的 ...

  6. MVC路由探寻,涉及路由的惯例、自定义片段变量、约束、生成链接和URL等

    引子 在了解MVC路由之前,必须了解的概念是"片段".片段是指除主机名和查询字符串以外的.以"/"分隔的各个部分.比如,在http://site.com/Hom ...

  7. Asp.Net MVC 路由 - Asp.Net 编程 - 张子阳

    http://cache.baiducontent.com/c?m=9d78d513d98316fa03acd2294d01d6165909c7256b96c4523f8a9c12d522195646 ...

  8. ASP.NET MVC 路由进阶(之二)--自定义路由约束

    3.自定义路由约束 什么叫自定义路由约束呢?假如路由格式为archive/{year}/{month}/{day},其中year,month,day是有约束条件的,必须是数字,而且有一定范围. 这时候 ...

  9. 自定义MVC路由配置

    首先我用MVC4新增一个订单查看的功能 1.创建控制器OrderController namespace MvcApplication3.Controllers { public class Orde ...

随机推荐

  1. 修复lsp,360浏览器可以上网其它软件不行

    netsh winsock reset netsh int ip reset 重启电脑

  2. A*寻路算法详解

    以我个人的理解: A*寻路算法是一种启发式算法,算法的核心是三个变量f,g,h的计算.g表示 从起点 沿正在搜索的路径 到 当前点的距离,h表示从当前点到终点的距离,而f=g+h,所以f越小,则经过当 ...

  3. Zabbix系列-REHL6.10离线方式安装Zabbix 4.0 LTS

    环境 第零步:关闭系统默认防火墙 setenforce 0 sed -i -r "/^SELINUX=/c SELINUX=disabled" /etc/selinux/confi ...

  4. Shader渲染动画

    一.概述 先看一下Shader类的介绍: /** * Shader is the based class for objects that return horizontal spans of col ...

  5. Python 不同列表时间测试

    import timeit import threading def test1(): l = [] for i in range(1000): l = l + [i] def test2(): l ...

  6. Java工具类使用注意事项

    (以下摘自阿里巴巴Java开发手册) 1. [强制]获取单例对象需要保证线程安全,其中的方法也要保证线程安全. 说明:资源驱动类.工具类.单例工厂类都需要注意. 5. [强制]SimpleDateFo ...

  7. Hibernate 事务和并发控制

    首先关于Hibernate事务控制,下面是非常权威的资料, https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch02.html ...

  8. 专访Bruce Douglass,谈嵌入式经验

     Bruce:表面上看,编程就是想要实现什么就写什么代码:但事实是,敲代码只是软件开发过程中很小的一部分,程序员的工作还包括安全分析.责任分析.产品验证.产品分析等.      =========== ...

  9. hdu 2577 模拟

    #include<stdio.h> #define N 200 char s[N]; int judgeup(char c) { if(c>='A'&&c<=' ...

  10. [using_microsoft_infopath_2010]Chapter10 与SharePoint Designer工作流集成

    本章概要: 1.创建工作流集成表单 2.允许工作流手动触发 3.创建自定义动作按钮 4.使用人物设计器 5.维护工作流人物表单