Asp.net mvc ** 中,来自客户端的请求总是针对某个 Controller 中的 Action 方法,因此,必须采用某种机制从请求的 URl 中解析出对应的 ControllerAction 的名称,这个过程便称为路由(Routing**)

路由(Routing) 机制并不是专属于 Asp.net mvc,而是建立在 **Asp.net ** 上的,与其相关的核心类型都定义在 System.Web 程序集中

路由机制的优势

  与之前的 Web From 应用的每次请求的都是针对某一物理文件相比,路由机制具有如下的优势:

  • 灵活性。当请求的物理文件的名称或者路径发生改变时,无需修改现有的路由,因为路由将物理文件的路径与请求完全的分离
  • 可读性。采用路由机制后,可以很容易的从请求的 Url 中看出本次请求的目的或或者要获取的信息
  • SEO优化。路由机制下的 Url 更符合搜索引擎的检索规则。

核心类型

  • RouteBase

    路由机制中的所有的路由对象都为抽象类 RouteBase 的子类,其定义如下:
    public abstract class RouteBase
{
private bool _routeExistingFiles = true; protected RouteBase()
{
} public abstract RouteData GetRouteData(HttpContextBase httpContext);
public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); public bool RouteExistingFiles
{
get =>
this._routeExistingFiles;
set
{
this._routeExistingFiles = value;
}
}
}

  从中可以看出,其有两个核心的方法 GetRouteDataGetVirtualPath,前者用于根据当前的 HttpContext 去获取与当前请求匹配的 RouteData,后者用于根据匹配的路由和传递的 Values 生成 Url,其中的参数 RequestContext 是对 HttpContextRouteData 的封装。

  • Route

      默认情况下,RouteBase 具有一个实现类 Route,其定义如下(部分):
    public class Route : RouteBase
{
public Route(string url, IRouteHandler routeHandler) public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) public override RouteData GetRouteData(HttpContextBase httpContext) public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) public RouteValueDictionary Constraints { get; set; } public RouteValueDictionary DataTokens { get; set; } public RouteValueDictionary Defaults { get; set; } public IRouteHandler RouteHandler { get; set; } public string Url {get;set;}
}

  其中的 Url 表示注册的路由的模板,例如 /{controller}/{action}/{id}, Defaults 表示路由的默认值,例如 new {controller="home",action="index",id = UrlParameter.Optional}, UrlParameter.Optional 表示该参数是可选的 , constraints 表示 对当前定义的路由规则的一些约束,例如,constrains:new {id = @"\d+"},限制 参数id为数字 例如将RouteHandler 表示对匹配该路由的请求处理使用的 IRouteHandler 类型的对象,其具有一个 返回 IHttpHandler GetHttpHandler(RequestContext context)的方法,IHttpHandler 中定义了一个 void ProcessRequest(HttpContext context) 是整个 Asp.net 应用进行后续处理的入口。

  • RouteData

      RouteData 中封存通过路由机制从请求的 Url 中解析出来的路由数据,其定义如下(部分):

      
    public class RouteData
{
public RouteData() public RouteData(RouteBase route, IRouteHandler routeHandler) public string GetRequiredString(string valueName) public RouteValueDictionary DataTokens{get;} public RouteBase Route { get; set; } public IRouteHandler RouteHandler{get;set;} public RouteValueDictionary Values{get;}
}

  上面的 Route 对象的 GetRouteData 返回的就是这样的一个 RouteData 对象,其中的 Route 就是与当前请求匹配的路由对象,RouteHandler 对应着 Route 对象的同名属性,Values 中保存从请求 Url 中解析出来的数据(键值对),如 controlleractionid 等,DataTokens 亦对应着 Route 对象的同名属性 。

  GetRequiredString(string valueName) 方法根据指定的 Key(valueName) 从 Values 中获取对应的值。如果指定的 key 不存在,则会抛出 InvalidOperation 的异常。

  • RouteTable

      RouteTable 类的定义比较简单,除了构造函数外,只有一个 RouteCollection 类型的静态属性 Routes,全局的路由注册便是通过该属性进行操作的。

      RouteCollection 派生自 Collection,其定义如下(部分核心):
    public class RouteCollection : Collection<RouteBase>
{
private Dictionary<string, RouteBase> _namedMap;
private ReaderWriterLockSlim _rwLock;
private VirtualPathProvider _vpp; public RouteCollection() public RouteCollection(VirtualPathProvider virtualPathProvider) public RouteData GetRouteData(HttpContextBase httpContext) public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values)
public void Ignore(string url) public void Ignore(string url, object constraints) public Route MapPageRoute(string routeName, string routeUrl, string physicalFile) public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens) public bool AppendTrailingSlash { get; set; } public RouteBase this[string name] public bool LowerCaseUrls{get;set;}
public bool RouteExistingFiles { get; set; }
}

  上面的代码可以看到其中定义了 RouteData GetRouteData(HttpContextBase context)VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values),在调用这两个方法时内部是通过调用集合内每个 Route 的同名方法,返回匹配的项,如果不存在则返回 null

  Ignore(string url) 方法将无需通过路由的资源对应的 Url 添加到路由表中,其内部会调用 Add 方法,参数 constraint 的作用同 Route 对象的同名参数,即对当前的路由进行约束。

  Route MapPageRoute() 方法,将指定的路由信息注册到当前的路由表中,其内部会调用 Add 方法,因此,除了使用 MapPageRoute 方法进行路由注册外,还可以直接调用 Add 方法,两者唯一的区别就是前者会返回一个添加的 Route 对象 ,后者则无返回值。 添加的 Route 对象的 IRouteHandler 均为 PageRouteHandler

  • AppendTrailingSliash 标识是否在生成的 Url 后添加 /
  • LowerCaseUrls 标识是否将生成的 Url 转换为小写
  • RouteExistingFiles 标识是否对物理文件进行路由

  在 Asp.net mvc 中对 RouteCollection 类进行了扩展,扩展方法定义在 System.Web.Mvc 程序集的 HttpRouteCollectionExtensions 类中,定义如下(部分核心方法):

    public static void IgnoreRoute(this RouteCollection routes, string url);
public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
public static Route MapRoute(this RouteCollection routes, string name, string url);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);

  上面的代码定义了两组方法,其中 IgnoreRoute 用于注册需要被忽略的 url 对应的路由模板,对应 RouteCollectionIgnore 方法,MapRoute 用于注册路由,对应 RouteCollectionMapPageRoute 方法。但与 MapPageRoute 不同的是原来的 constraintsdefaultsRouteValueDictionary 变为了 object,这样我们可以通过匿名参数的方式来为其赋值,在方法的内部会通过反射的方式获取对象的属性列表,然后将其转换为 RouteValueDictionary,其 keyvalue 分别为属性的名称与属性值。MapPageRoute 方法中调用 Add 方法时指定的 IRouteHanndlerPageRouteHandlerMapRoute 方法内部调用 Add 方法时指定的 IRouteHandler 为 **MvcRouteHandler **

路由解析整体过程

路由扩展(定制)思路

  • 通过继承 RouteBase 抽象类自定义路由实现自定义路由逻辑
  • 通过实现 IRouteHandler 接口自主实现 RouteHandler 的提供机制(RouteCollection.Add(name,IRouteHandler))
  • 通过实现 IHttpHandler 接口自主实现请求的处理并返回(HttpContextBase.RemapHandler(IHttpHandler))

Asp.net mvc 中的路由的更多相关文章

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

    一.概述 在ASP.NET MVC架构中,控制器在3大核心构件中处于中心地位,通过控制器支配模型和视图,然而从浏览器发出的请求到控制器还需要路由的协助,路由将特定的请求和控制器的动作对应起来. 在AS ...

  2. ASP.NET MVC中的路由IRouteConstraint方法应用实例

    在如下代码的写法中: public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { ro ...

  3. asp.net mvc中的路由

    [Route] 路由 [Route("~/")] 忽略路由前缀 [Route("person/{id:int}")] 路由内联约束 [Route("h ...

  4. asp.net mvc中配置路由默认值(Area中)

    public class RouteConfig { ] { "Best.Site.Areas.BestPalace" }; public static void Register ...

  5. 【翻译】ASP.NET MVC 5属性路由(转)

    转载链接:http://www.cnblogs.com/thestartdream/p/4246533.html 原文链接:http://blogs.msdn.com/b/webdev/archive ...

  6. Asp.net mvc 中Action 方法的执行(一)

    [toc] 在 Aps.net mvc 应用中对请求的处理最终都是转换为对某个 Controller 中的某个 Action 方法的调用,因此,要对一个请求进行处理,第一步,需要根据请求解析出对应的 ...

  7. angular.js的路由和模板在asp.net mvc 中的使用

    angular.js的路由和模板在asp.net mvc 中的使用 我们知道angular.js是基于mvc 的一款优秀js框架,它也有一套自己的路由机制,和asp.net mvc 路由不太一样.as ...

  8. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

  9. 如何在 ASP.NET MVC 中集成 AngularJS(2)

    在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...

随机推荐

  1. 关于oracle数据库 跨表查询建立 视图的方法

    工作中很多时候都会遇到需要将两个不同的表空间甚至数据库的表进行联合查询或者建立视图的情况. 不同的表空间查询我们可以通过在将要查询的表前面加上 表空间的对应的用户名来实现,如有两个表空间分别对应两个用 ...

  2. C#后台生成验证码

    https://www.cnblogs.com/vchenpeng/archive/2013/05/12/3074887.html /// <summary>          /// 获 ...

  3. 洛谷 P1485 火枪打怪

    题目描述 LXL进入到了一片丛林,结果他发现有n只怪物排成一排站在他面前.LXL有一杆火枪能对付这些怪物.他知道从左至右数第i只怪物的血量是mi.现在LXL可以将一些子弹射向某个怪物.LXL可以控制他 ...

  4. MySQL优化五 SQL优化

    1.减少 IO 次数 IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当然 ...

  5. MicroPython教程之TPYBoard v102 CAN总线通信

    0x00前言 CAN是控制器局域网络(ControllerAreaNetwork,CAN)的简称,是ISO国际标准化的串行通信协议.CAN总线结构简单,只需2根线与外部相连,并且内部集成了错误探测和管 ...

  6. Windows上最大传输单元MTU值的查看和设置

    最近使用ssh工具在VPN环境下连接一个生产环境的Linux主机的时候,发现经常出现输入命令后卡死的情况.最开始以为是Linux主机的问题,问了一些老同事之后发现原来是我自己电脑的最大传输单元MTU和 ...

  7. Git知识总览(二) git常用命令概览

    上篇博客我们从 git clone 和 git status 两个命令开始,引出了一系列的git操作命令, 请参见:<Git知识总览(一) 从 git clone 和 git status 谈起 ...

  8. Python使用Tabula提取PDF表格数据

    今天遇到一个批量读取pdf文件中表格数据的需求,样式大体是以下这样: python读取PDF无非就是三种方式(我所了解的),pdfminer.pdf2htmlEX 和 Tabula.综合考虑后,选择了 ...

  9. Java—javac Hello.java找不到文件

    刚开始编写Java代码时,会遇到很多困难,下面来说一个比较常见的错误,如下: 对于初学者,一般都是从Hello,World开始的学起的,废了好大劲儿,铜鼓了半天,终于要在DOS上运行javac Hel ...

  10. 一键下载你的youtube视频

    很多人喜欢逛油管看视频,自然就会有一些喜欢的收藏集或者视频作者,有时候想要下载下来保存在本地播放,这样的话就不用每次FQ,毕竟有些代理的速度并不是很理想(如果你的代理速度炒鸡快的话,请忽略这篇文章). ...