• MVC中的URL路由(一)


      URL路由系统通过对请求地址进行解析从而得到以目标Controller名称为核心的路由数据。Url路由系统最初是为了实现请求url与物理文件路径分离而建立的,MVC的Url Route是将Url地址与物理文件映射转移到了目标Controller的映射。

    Url路由不是ASP.NET MVC特有的,而是建立在ASP.NET上面的,MVC的只是对这个路由的拓展使用(asp.net也开始使用这拓展了)。

      我们在App_Start文件夹中找到RouteConfig.cs的文件,打开看

     1         public static void RegisterRoutes(RouteCollection routes)
     2         {
     3             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
     4 
     5             routes.MapRoute(
     6                 name: "Default",
     7                 url: "{controller}/{action}/{id}",
     8                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
     9             );
    10         }

      大体可以猜出什么意思,url那一栏地址中第一个是controller,第二个是action,第三个是参数id,defaults是默认的参数,然后在Global.asax对该路由进行注册。

      

    1         protected void Application_Start()
    2         {
    3             AreaRegistration.RegisterAllAreas();
    4             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    5             RouteConfig.RegisterRoutes(RouteTable.Routes);
    6             BundleConfig.RegisterBundles(BundleTable.Bundles);
    7         }

      

      简单来说路由的任务:检查请求的URL,找出当前请求的是哪个controller中的哪个action,并且有无带了什么参数过来。

     

      那好,我们来分析一下请求一个地址的时候,路由系统发生了什么事情?我们先来大胆的猜一下:类似于网络设备的路由器,它会有一个路由表,根据我们配置的规则对端口过来的数据进行转发,这张表里就记录了匹配规则跟处理的程序,当一个数据包过来的时候,去这张表里面寻找所相应的发送地址,找到的话路由系统就将这数据包发往哪个对应的地址里面。

     

      按照上面逻辑的话,我们先来找找匹配的规则在哪里加上来的,我们在上面的静态方法里面看到有一个RouteCollection的东西,进去看看里面有啥?

      

      发现了一个MapPageRoute的方法

      

     1         //
     2         // 摘要: 
     3         //     提供用于定义 Web 窗体应用程序的路由的方法。
     4         //
     5         // 参数: 
     6         //   routeName:
     7         //     路由的名称。
     8         //
     9         //   routeUrl:
    10         //     路由的 URL 模式。
    11         //
    12         //   physicalFile:
    13         //     路由的物理 URL。
    14         //
    15         // 返回结果: 
    16         //     将添加到路由集合的路由。
    17         public Route MapPageRoute(string routeName, string routeUrl, string physicalFile);

      

      可以看到我们调用RouteCollection的MapPageRoute方法将某个物理文件路径映射到一个URL模板上,这个过程其实就是基于指定的url模板创建一个路由对象,并且将他添加到这个全局路由表中,那程序是在哪里有个Add的入口呢?不小心在RouteCollection里面发现了一个Add的方法

      

     1         // 摘要: 
     2         //     将路由添加到 System.Web.Routing.RouteCollection 对象的结尾,并为路由分配指定的名称。
     3         //
     4         // 参数: 
     5         //   name:
     6         //     标识路由的值。 该值可为 null 或空字符串。
     7         //
     8         //   item:
     9         //     要添加到集合结尾的路由。
    10         //
    11         // 异常: 
    12         //   System.ArgumentNullException:
    13         //     item 为 null。
    14         //
    15         //   System.ArgumentException:
    16         //     name 已在集合中使用。
    17         public void Add(string name, RouteBase item);

      

      可以看到这里添加了一个Routebase的东西,我们点击去看看是什么来头?

      

     1     // 摘要: 
     2     //     用作表示 ASP.NET 路由的所有类的基类。
     3     [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
     4     public abstract class RouteBase
     5     {
     6         // 摘要: 
     7         //     初始化该类供继承的类实例使用。 此构造函数只能由继承的类调用。
     8         protected RouteBase();
     9 
    10         // 摘要: 
    11         //     获取或设置一个值,该值指示 ASP.NET 路由操作是否应处理与现有文件匹配的 URL。
    12         //
    13         // 返回结果: 
    14         //     如果 ASP.NET 路由操作处理所有请求(甚至包括与现有文件匹配的请求),则为 true;否则为 false。 默认值为 false。
    15         public bool RouteExistingFiles { get; set; }
    16 
    17         // 摘要: 
    18         //     当在派生类中重写时,会返回有关请求的路由信息。
    19         //
    20         // 参数: 
    21         //   httpContext:
    22         //     一个对象,封装有关 HTTP 请求的信息。
    23         //
    24         // 返回结果: 
    25         //     一个对象,包含路由定义的值(如果该路由与当前请求匹配)或 null(如果该路由与请求不匹配)。
    26         public abstract RouteData GetRouteData(HttpContextBase httpContext);
    27         //
    28         // 摘要: 
    29         //     当在派生类中重写时,会检查路由是否与指定值匹配,如果匹配,则生成一个 URL,然后检索有关该路由的信息。
    30         //
    31         // 参数: 
    32         //   requestContext:
    33         //     一个对象,封装有关所请求的路由的信息。
    34         //
    35         //   values:
    36         //     一个包含路由参数的对象。
    37         //
    38         // 返回结果: 
    39         //     一个对象(包含生成的 URL 和有关路由的信息)或 null(如果路由与 values 不匹配)。
    40         public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
    41     }

      我们看到了两个抽象方法:GetRouteData与GetVirtualPath,当一个请求过来的时候,它们都会去根据URL模板的模式与代表请求地址的URL地址进行匹配,如果匹配失败返回null,成功的话,GetRouteData会得到一个封装了路由信息的RouteData对象,而GetVirtualPath则会生成一个URL,该URL被封装成VirtualPathData对象进行返回。

      那通过以上猜测,我们知道了路由系统物理文件路径添加到一个全局的路由表中,并传入给定的参数调用同名方法去找到一个与指定请求URL相匹配的路由对象,并返回相应的RouteData和VirtualPathData对象。

      好了,简单的Url就写就这里了,稍后会对下一步进行详解,尽请期待!

  • 相关阅读:
    企业库连接形式简单例子记录 EnterpriseLibrary.Data
    .net 抽象类(abstract)和接口(interface)区别
    windows service 开发、安装及调试
    asp.net(mvc) 框架
    获取IP地址
    select2 模糊查询远程数据
    设计模式篇——初探命令模式
    初探MVC路由
    初探表达式目录树
    C#实现插入排序法
  • 原文地址:https://www.cnblogs.com/powerdk/p/4240431.html
Copyright © 2020-2023  润新知