• ASP.NET 路由解析


    这段时间在读园子里Artech大神的《ASP.NET MVC5框架揭秘》,慢慢地从底层了解了MVC模式的设计思路。下面是一些阅读的总结。

    传统的Web Forms应用,URL指向的是具体的物理文件,而ASP.NET MVC应用一般指向的是某个Controller中的某个Action方法。URL与目标Controller/Action之间的映射关系是通过“路由”来实现的。

    路由系统中的几个核心类的描述:

    RouteBase

    • 一个抽象基类。
    public abstract class RouteBase
    {
     //.NET Framwork4.5以下无该属性(是否对物理文件采取路由) public bool RouteExistingFiles { get; set; }
     //获取路由数据 public abstract RouteData GetRouteData(HttpContextBase httpContext);
     //路由解析生成一个完整的路径 public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); }

    RouteData

    • 封装了有关路由的信息。
    • RouteData通过其RouteHandler属性返回一个RouteHandler对象。
    • RouteHandler实现IRouteHandler中的GetHttpHandler(RequestContext requestContext),返回一个具的HttpHandler对象接管http请求。
        public class RouteData
        {
            public RouteData();
            public RouteData(RouteBase route, IRouteHandler routeHandler);
            public string GetRequiredString(string valueName);
    
            public RouteBase Route { get; set; }
            public IRouteHandler RouteHandler { get; set; }
         public RouteValueDictionary DataTokens { get; }
            public RouteValueDictionary Values { get; }
        }

    VirtualPathData

    • 表示有关路由和虚拟路径的信息。
    • 执行RouteBase的GetVirtualPath()会进行路由匹配,将路由变量去替换路由模板中的占位符并生成虚拟路径。
    • 此类为虚拟路径和Route的封装。
    public class VirtualPathData
    {
      public VirtualPathData(RouteBase route, string virtualPath);
      public RouteValueDictionary DataTokens { get; }
      public RouteBase Route { get; set; }
      public string VirtualPath { get; set; }
    }

     Route

    • 提供用于定义路由及获取路由相关信息的属性和方法。
    • 路由解析由路由表中具体的某个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 RouteValueDictionary Constraints { get; set; }
         //存储额外的变量,不参与路由解析
    public RouteValueDictionary DataTokens { get; set; } public RouteValueDictionary Defaults { get; set; } public IRouteHandler RouteHandler { get; set; } public string Url { get; set; } public override RouteData GetRouteData(HttpContextBase httpContext); public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); }

     RouteTable

    • 存储应用程序的 URL 路由。
    • 静态只读属性Routes访问全局路由表。
    public class RouteTable
    {
        public static RouteCollection Routes { get; }
    }

    RouteCollection

    • 一组Route的集合,用来操作Route。
    • 调用RouteCollection的GetRouteData和GetVirtualPath时会遍历集合中的所有Route。
    • 常用的两个方法。MapPageRoute:注册路由。Ignore:忽略对应的URL格式。


    总结下类之间的关系:

    Route对象代表一条实际的路由规则。调用Route对象的两个路由匹配方法时进行路由解析,返回的RouteData或VirtualPathData是对Route的封装。RouteTable存储了Web应用的全局路由信息,即多个Route对象。

    路由注册

    • MVC4中默认的路由注册
       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 }
                );
            }
    • 书中带约束的注册方式
       public static void RegisterRoutes(RouteCollection routes)
            {
           //默认值
    var defaults = new RouteValueDictionary{ {"areacode","010"},{"days",2}};
           //正则约束
    var constaints = new RouteValueDictionary { {"areacode",@"0d{2,3}"},{"days",@"[1-3]{1}"}};
           //说明
    var dataTokens = new RouteValueDictionary{ {"defaultCitry","BeiJing"},{"defaultDays",2}}; routes.MapPageRoute("default","{areacode}/{}days","~/weather.aspx" ,false,defaults,constaints,dataTokens); }

    正则约束是其中一个比较简单的方法,我们还可以通过自定义约束来实现。实现IRouteConstraint的Match方法。

    假设现在我们要通过IRouteConstraint来限制IE浏览器的访问。

    public class IERouteConstraint : IRouteConstraint
    {
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            return !(httpContext.Request.UserAgent.Contains("MSIE"));
        }
    }
    //在原来的约束基础上修改
    var constaints = new RouteValueDictionary {
        {"areacode",@"0d{2,3}"},{"days",@"[1-3]{1}"},new IERouteConstraint()};

    注:针对自定义路由约束的详细内容,请移步:http://www.cnblogs.com/xfrog/archive/2010/12/19/1910428.html。此例也选自该博文。

    从HTTP请求到路由解析

    1. URLRoutingModule派生自IHttpModule。通过它注册HttpApplication的PostResolveRequestCache事件。
    2. 当一个HttpApplication对象触发该事件后,URLRoutingModule通过RouteTable的静态只读属性Routea得到全局的路由表的RouteCollection对象,然后根据当前的上下文创建一个HttpContextWrapper对象(派生自HttpContextBase),并将其作为参数调用RouteCollection对象的GetRouteData方法。
    3. 如果路由匹配成功,会返回一个具体的RouteData对象。
    4. URLRoutingModule会将HttpContextWrapper传入RouteData对象中的RouteHandler。调用它的GetHttpHandler方法,得到一个具体的HttpHandler。URLRoutingModule最后调用HttpContextWrapper对象的RemapHandler方法对得到的HttpHandler进行映射。
    5. 解析完成,针对当前的HTTP请求就由该Handler来接手。

     注:本博文大多数内容来自《ASP.NET MVC5框架揭秘》中,只是做内容的梳理和总结。

  • 相关阅读:
    linux centos 安装配置rsync
    linux下mysql权限配置
    让nginx支持patchinfo,(支持codeigniter,thinkphp,ZF等框架)
    nginx、php-fpm安装mongodb及驱动扩展
    redis和redis php扩展安装
    sea.js 入门
    require.js 入门笔记
    怎么玩耍图标字体.
    利用 Gulp 处理前端工作流程
    LESS 学习记录(简单入门)
  • 原文地址:https://www.cnblogs.com/Sinte-Beuve/p/4232234.html
Copyright © 2020-2023  润新知