博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC 路由系统类
阅读量:6527 次
发布时间:2019-06-24

本文共 11721 字,大约阅读时间需要 39 分钟。

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.
k__BackingField; } set { this.
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获取当前的RouteData ,GetVirtualPath方法获取相关的虚拟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
pair in values) { data.Values.Add(pair.Key, pair.Value); } if (this.DataTokens != null) { foreach (KeyValuePair
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
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
pair in this.Constraints) { if (!this.ProcessConstraint(httpContext, pair.Value, pair.Key, values, routeDirection)) { return false; } } } return true; } public RouteValueDictionary Constraints { get { return this.
k__BackingField; } set { this.
k__BackingField = value; } } public RouteValueDictionary DataTokens { get { return this.
k__BackingField; } set { this.
k__BackingField = value; } } public RouteValueDictionary Defaults { get { return this.
k__BackingField; } set { this.
k__BackingField = value; } } public IRouteHandler RouteHandler { get { return this.
k__BackingField; } set { this.
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方法的执行过程可以参考写的;

RouteCollection

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

 

public class RouteCollection : Collection
{ ............. 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;            }        }    }

 

转载于:https://www.cnblogs.com/h20064528/p/4121472.html

你可能感兴趣的文章
LOJ#2095 选数
查看>>
Ubuntu 16.04 Steam
查看>>
Turbo Boost是什么?最高睿频是什么?
查看>>
onScrollChanged()
查看>>
c#多态
查看>>
单独使用bable插件
查看>>
// 查询字符串转json
查看>>
第四十天笔记
查看>>
4、动态代理
查看>>
Loj #6073.「2017 山东一轮集训 Day5」距离
查看>>
我的TCP/IP学习笔记
查看>>
刷碗效应
查看>>
ie7下<a></a>标签中<input />时不反应
查看>>
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
查看>>
POJ1011 Sticks
查看>>
前言:数据库典型架构实践
查看>>
使用fat-jar打包多个java工程为可执行文件
查看>>
Fluent NHibernate之旅
查看>>
python基础知识
查看>>
【机器学习】--GBDT算法从初始到应用
查看>>