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;
}
}
}
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() + 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;
}
}
}
在我们调用的 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 != )
{
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;
}
}
}
ASP.NET MVC 路由系统类的更多相关文章
- asp.net MVC 路由系统
ASP.NET的路由系统是基于物理文件的路由注册,通过调用System.Routing.RouteTable的Routes(RouteCollection)属性的MapPageRoute()方法来完成 ...
- asp.net Mvc 路由详解,非常详细.
关于路由的理解 为什么要定义路由?路由的定义在开发中的工作量非常小,但是非常重要,因为任何请求都离不开路由. 各个电商网站的 URL 使用非常灵活,都离不开路由的定义,请大家参考几家电商的 URL 如 ...
- ASP.NET MVC , ASP.NET Web API 的路由系统与 ASP.NET 的路由系统是怎么衔接的?
ASP.NET MVC 的路由实际上是建立在 ASP.NET 的路由系统之上的. MVC 路由注册通常是这样的: RouteTable 是一个全局路由表, 它的 Routes 静态属性是一个 Ro ...
- ASP.NET MVC 路由(二)
ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...
- ASP.NET MVC 路由(三)
ASP.NET MVC路由(三) 前言 通过前两篇的学习会对路由系统会有一个初步的了解,并且对路由系统中的Url规则有个简单的了解,在大家的脑海中也有个印象了,那么路由系统在ASP.NETMVC中所处 ...
- ASP.NET MVC 路由(四)
ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...
- ASP.NET MVC路由
ASP.NET MVC路由(四) 前言 在前面的篇幅中我们讲解路由系统在MVC中的运行过程以及粗略的原理,想必看过前面篇幅的朋友应该对路由有个概念性的了解了,本篇来讲解区域,在读完本篇后不会肯定的让你 ...
- asp.net MVC 路由机制
1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...
- asp.net MVC 路由机制 Route
1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...
随机推荐
- mysql 及练习题
if() 函数的用法 IF(expr1,expr2,expr3),如果expr1的值为true,则返回expr2的值,如果expr1的值为false, mysql,'女','男') as sex fr ...
- fzu1901Period II
地址:http://acm.fzu.edu.cn/problem.php?pid=1901 题目: Problem 1901 Period II Accept: 442 Submit: 1099 ...
- IDEA 程序直接运行分析
今天用IDEA运行SpringBoot程序,启动时始终报错说读取不到datasource的url配置. 分析代码的resources目录,是有配置文件的,配置也是正常的.如下图: 后来经人指点,是因为 ...
- 关于hashmap 与concurrentHashMap
hashmap是不安全的,要实现安全,可以用Collections里面的synchronizedMap包裹来实现安全,或者用concurrentMap, 注意:hashtable是安全的 从JDK1. ...
- Send2MyKindle使用说明文档
软件下载地址为:Send2MyKindle 功能简介 该软件主要功能为在Windows下将Kindle电子书发送到亚马逊中国网站注册的Kindle账户.整个软件界面如下图所示: 使用步骤 使用前的准备 ...
- innodb 行级锁
InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,In ...
- 关于JavaScript对象,你所不知道的事(一)- 先谈对象
这篇博文的主要目的是为了填坑,很久之前我发表了一篇名为关于JavaScript对象中的一切(一) - 对象属性的文章,想要谈一谈JavaScript对象,可那时只是贴了一张关于这个主题的思维导图,今天 ...
- centos查看是否安装了某个软件
1. rpm包安装的,可以用rpm -qa看到,如果要查找某软件包是否安装,用 rpm -qa | grep "软件或者包的名字". 2. yum方法安装的,可以用yum list ...
- list<>泛型的意义
泛型就是指定一个自定类或数据类型例如(int)并命名一个XXX集合名,所有这个类型的数据可以加入这个XXXX集合名,组成一个集合. private list<可放例int数据类型或自定类> ...
- 【链接】Eclipse的Debug调试技巧
Eclipse的Debug调试技巧大全 https://mp.weixin.qq.com/s/bORg9YxJiby2WenYRrXY-w 使用Eclipse调试Java程序的10个技巧 https: ...