zoukankan      html  css  js  c++  java
  • ASP.NET MVC 路由系统类

    RouteData

     public class RouteData
        {
            private RouteValueDictionary _dataTokens;
            private IRouteHandler _routeHandler;
            private RouteValueDictionary _values;
            public RouteData()
            {
                this._values = new RouteValueDictionary();
                this._dataTokens = new RouteValueDictionary();
            }
    
            public RouteData(RouteBase route, IRouteHandler routeHandler)
            {
                this._values = new RouteValueDictionary();
                this._dataTokens = new RouteValueDictionary();
                this.Route = route;
                this.RouteHandler = routeHandler;
            }
    
            public string GetRequiredString(string valueName)
            {
                object obj2;
                if (this.Values.TryGetValue(valueName, out obj2))
                {
                    string str = obj2 as string;
                    if (!string.IsNullOrEmpty(str))
                    {
                        return str;
                    }
                }
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, System.Web.SR.GetString("RouteData_RequiredValue"), new object[] { valueName }));
            }
    
            public RouteValueDictionary DataTokens
            {
                [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
                get
                {
                    return this._dataTokens;
                }
            }
    
            public RouteBase Route
            {
                get
                {
                    return this.<Route>k__BackingField;
                }
                set
                {
                    this.<Route>k__BackingField = value;
                }
            }
    
            public IRouteHandler RouteHandler
            {
                get
                {
                    return this._routeHandler;
                }
                set
                {
                    this._routeHandler = value;
                }
            }
    
            public RouteValueDictionary Values
            {
                get
                {
                    return this._values;
                }
            }
        }
    View Code

         RouteData 封装有关路由的信息的类;属性DataTokens是个字典集合,主要存储传递到路由处理程序但未使用的自定义值的集合。比如说Namespace等;

    属性Route表示当前的路由的对象,属性Values表示的是路由的 URL 参数值和默认值的集合。属性RouteHandler是继承IRouteHandler的接口的类,在IRouteHandler接口中的GetHttpHandler方法获取到处理页面请求的IHttpHandler;在MVC中RouteData的对象的RouteHandler一般为MvcRouteHandler或是StopRoutingHandler

        public interface IRouteHandler
        {
            IHttpHandler GetHttpHandler(RequestContext requestContext);
        }

    RouteBase

        public abstract class RouteBase
        {
            private bool _routeExistingFiles = true;
            protected RouteBase()
            {
            }
            // 当在派生类中重写时,会返回有关请求的路由信息。
            public abstract RouteData GetRouteData(HttpContextBase httpContext);
    //当在派生类中重写时,会检查路由是否与指定值匹配,如果匹配,则生成一个 URL,然后检索有关该路由的信息
    public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values); public bool RouteExistingFiles// 如果 ASP.NET 路由操作处理所有请求(甚至包括与现有文件匹配的请求),则为 true;否则为 false。 默认值为 false。 { get { return this._routeExistingFiles; } set { this._routeExistingFiles = value; } } }
    RouteBase 为Route的抽象基类,有2个抽象方法GetRouteData获取当前的RouteDataGetVirtualPath方法获取相关的虚拟url;

    Route

      Route类提供用于定义路由及获取路由相关信息的属性和方法,Route类继承了RouteBase 类,并重写了RouteBase 中的GetRouteData方法和GetVirtualPath方法;

    public class Route : RouteBase
        {
            private ParsedRoute _parsedRoute;
            private string _url;
            private const string HttpMethodParameterName = "httpMethod";
            public Route(string url, IRouteHandler routeHandler)
            {
                this.Url = url;
                this.RouteHandler = routeHandler;
            }
            public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
            {
                this.Url = url;
                this.Defaults = defaults;
                this.RouteHandler = routeHandler;
            }
    
            public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
            {
                this.Url = url;
                this.Defaults = defaults;
                this.Constraints = constraints;
                this.RouteHandler = routeHandler;
            }
    
            public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            {
                this.Url = url;
                this.Defaults = defaults;
                this.Constraints = constraints;
                this.DataTokens = dataTokens;
                this.RouteHandler = routeHandler;
            }
    
            public override RouteData GetRouteData(HttpContextBase httpContext)
            {
                string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
                RouteValueDictionary values = this._parsedRoute.Match(virtualPath, this.Defaults);
                if (values == null)
                {
                    return null;
                }
                RouteData data = new RouteData(this, this.RouteHandler);
                if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
                {
                    return null;
                }
                foreach (KeyValuePair<string, object> pair in values)
                {
                    data.Values.Add(pair.Key, pair.Value);
                }
                if (this.DataTokens != null)
                {
                    foreach (KeyValuePair<string, object> pair2 in this.DataTokens)
                    {
                        data.DataTokens[pair2.Key] = pair2.Value;
                    }
                }
                return data;
            }
    
            public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
            {
                BoundUrl url = this._parsedRoute.Bind(requestContext.RouteData.Values, values, this.Defaults, this.Constraints);
                if (url == null)
                {
                    return null;
                }
                if (!this.ProcessConstraints(requestContext.HttpContext, url.Values, RouteDirection.UrlGeneration))
                {
                    return null;
                }
                VirtualPathData data = new VirtualPathData(this, url.Url);
                if (this.DataTokens != null)
                {
                    foreach (KeyValuePair<string, object> pair in this.DataTokens)
                    {
                        data.DataTokens[pair.Key] = pair.Value;
                    }
                }
                return data;
            }
            protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
            {
                object obj2;
                IRouteConstraint constraint2 = constraint as IRouteConstraint;
                if (constraint2 != null)
                {
                    return constraint2.Match(httpContext, this, parameterName, values, routeDirection);
                }
                string str = constraint as string;
                if (str == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, System.Web.SR.GetString("Route_ValidationMustBeStringOrCustomConstraint"), new object[] { parameterName, this.Url }));
                }
                values.TryGetValue(parameterName, out obj2);
                string input = Convert.ToString(obj2, CultureInfo.InvariantCulture);
                string pattern = "^(" + str + ")$";
                return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
            }
    
            private bool ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection)
            {
                if (this.Constraints != null)
                {
                    foreach (KeyValuePair<string, object> pair in this.Constraints)
                    {
                        if (!this.ProcessConstraint(httpContext, pair.Value, pair.Key, values, routeDirection))
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
    
            public RouteValueDictionary Constraints
            {
                get
                {
                    return this.<Constraints>k__BackingField;
                }
                set
                {
                    this.<Constraints>k__BackingField = value;
                }
            }
    
            public RouteValueDictionary DataTokens
            {
             
                get
                {
                    return this.<DataTokens>k__BackingField;
                }
                set
                {
                    this.<DataTokens>k__BackingField = value;
                }
            }
    
            public RouteValueDictionary Defaults
            {
               
                get
                {
                    return this.<Defaults>k__BackingField;
                }
                set
                {
                    this.<Defaults>k__BackingField = value;
                }
            }
    
            public IRouteHandler RouteHandler
            {
                
                get
                {
                    return this.<RouteHandler>k__BackingField;
                }
                set
                {
                    this.<RouteHandler>k__BackingField = value;
                }
            }
    
            public string Url
            {
                get
                {
                    return (this._url ?? string.Empty);
                }
                set
                {
                    this._parsedRoute = RouteParser.Parse(value);
                    this._url = value;
                }
            }
        }
    View Code

    在我们调用的   routes.MapRoute方法时Route对象被创建;

    属性Url:获取或设置路由的 URL 模式。
    属性Constraints:取或设置为 URL 参数指定有效值的表达式的词典。添加到Constraints字典中的数据,必须是字符串或是满足IRouteConstraint接口的类;

    属性DataTokens: 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。比如Namespace,Area等数据;对应于RouteData中的DataTokens;

    属性 Defaults:获取或设置要在 URL 不包含所有参数时使用的值,

    属性 RouteHandler:对应于RouteData中的RouteHandler;

    关于 Route中的GetRouteData方法的执行过程可以参考dz45693写的asp.net mvc源码分析-Route的GetRouteData

    RouteCollection

    RouteCollection类是存储route的集合,在RouteCollection中存在GetRouteData方法时获取匹配当前的路由;

    public class RouteCollection : Collection<RouteBase>
    {
          .............
        
            public RouteData GetRouteData(HttpContextBase httpContext)
            {
                if (httpContext == null)
                {
                    throw new ArgumentNullException("httpContext");
                }
                if (httpContext.Request == null)
                {
                    throw new ArgumentException(System.Web.SR.GetString("RouteTable_ContextMissingRequest"), "httpContext");
                }
                if (base.Count != 0)
                {
                    bool flag = false;
                    bool flag2 = false;
                    if (!this.RouteExistingFiles)
                    {
                        flag = this.IsRouteToExistingFile(httpContext);
                        flag2 = true;
                        if (flag)
                        {
                            return null;
                        }
                    }
                    using (this.GetReadLock())
                    {
                        foreach (RouteBase base2 in this)
                        {
                            RouteData routeData = base2.GetRouteData(httpContext);
                            if (routeData != null)
                            {
                                if (!base2.RouteExistingFiles)
                                {
                                    if (!flag2)
                                    {
                                        flag = this.IsRouteToExistingFile(httpContext);
                                        flag2 = true;
                                    }
                                    if (flag)
                                    {
                                        return null;
                                    }
                                }
                                return routeData;
                            }
                        }
                    }
                }
                return null;
            }
    
    
          ..............
    }

          在RouteCollection.GetRouteData方法时,会循环变量当前的RouteCollection中的Route集合,如果能找到匹配的RouteData的话,直接返回,终止循环,从这里可以看出在定义Route的顺序很重要,尽量特殊的匹配

    规则写在前面;

    RouteTable

    RouteTable类很简单,就是包含一个RouteCollection类

         public class RouteTable
        {
            private static RouteCollection _instance = new RouteCollection();
    
            public static RouteCollection Routes
            {
                [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
                get
                {
                    return _instance;
                }
            }
        }
  • 相关阅读:
    linux/eclipse/c++ 动态库的创立与调用
    虚拟机NetworkAdapter三种方式的区别
    关于“三层架构”和MVC
    C# 扩展方法
    鼠标拖移对象
    获取应用程序根目录物理路径(Web and Windows)
    一个简单的管理Web站点文件的页面程序(修改版)
    一个基于jQuery的简单树形菜单
    以人为本的程序的设计
    一个加密解密的小工具及源码(MD5, DES, RSA)
  • 原文地址:https://www.cnblogs.com/h20064528/p/4121472.html
Copyright © 2011-2022 走看看