UrlRouting路由流程:

添加路由:可以通过调用MapRoute()、MapPageRoute(),它们内部都是创建Route对象,最终添加到RouteCollection中。

    还可以使用[Route("/home/index")]的方式添加,注册路由时需要执行RouteConfig.RegisterRoutes(RouteTable.Routes);

    或者直接调用RouteCollection.Add()方法注册路由

匹配路由:调用RouteCollection的GetRouteData(),最终调用Route中的GetRouteData(),如果返回非null,则匹配

排除路由:IgnoreRoute(),也是往RouteCollection中添加了一个Route对象,Route中的handler是StopRoutingHandler。在路由配置时,如果匹配到的路由的Handler是StopRoutingHandler,请求中断

说明:

MapRoute()是添加MVC路由,MapPageRoute()是添加WebForm路由。它们的RouteHandler不同,MVC的是MVCRouteHandler,WebForm的是PageRouteHandler

MVCRouteHandler内部可以获取到IHttpHandler,实现类是MVCHander,它的PR方法中创建Controller,并调用Action

PageRouteHandler同上,它的IHttpHandler的实现类是Page,Page中有几个事件,我们可以在事件回调中做操作。

MVC和WebForm都是用的ASP.NET框架,从路由开始有了差别,一个创建Controller,一个创建Page。

自定义Route:

可以自定义做一些限制等操作,比如限制域名

    /// <summary>
/// 支持泛域名的UrlRouting
/// </summary>
public class DomainRoute : RouteBase
{
#region 变量
private string _domainName;
private string _physicalFile;
private string _routeUrl;
private bool _checkPhysicalUrlAccess = false;
private RouteValueDictionary _defaults;
private RouteValueDictionary _constraints;
private IList<PathSegment> _pathSegmentLists = new List<PathSegment>();
private const string REPLACE_PATTEN = @"([\w,%]+)";
private readonly Regex _patten = new Regex(@"\{([a-z,A-Z,0-9]+)\}", RegexOptions.Compiled);
private int _segmentCount = ;
#endregion #region 构造函数
/// <summary>
///
/// </summary>
/// <param name="domainName">泛域名</param>
/// <param name="routeUrl">Url路由</param>
/// <param name="physicalFile">映射的物理文件</param>
/// <param name="checkPhysicalUrlAccess">一个值,该值指示 ASP.NET 是否应验证用户是否有权访问物理 URL(始终会检查路由 URL)。此参数设置 System.Web.Routing.PageRouteHandler.CheckPhysicalUrlAccess</param>
/// <param name="defaults">路由的默认值。</param>
/// <param name="constraints">一些约束,URL 请求必须满足这些约束才能作为此路由处理。</param> public DomainRoute(string domainName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)
{
this._domainName = domainName.ToLower();
this._routeUrl = routeUrl;
this._physicalFile = physicalFile;
this._checkPhysicalUrlAccess = checkPhysicalUrlAccess;
this._defaults = defaults;
this._constraints = constraints; IList<string> lists = SplitUrlToPathSegmentStrings(routeUrl);
if (lists != null && lists.Count > )
{
this._segmentCount = lists.Count;
for (int i = ; i < lists.Count; i++)
{
string strPatten = lists[i];
if (!string.IsNullOrWhiteSpace(strPatten) && this._patten.IsMatch(strPatten))
{
PathSegment segment = new PathSegment();
segment.Index = i; Match match;
List<string> valueNames = new List<string>();
for (match = this._patten.Match(strPatten); match.Success; match = match.NextMatch())
{
strPatten = strPatten.Replace(match.Groups[].Value, REPLACE_PATTEN);
valueNames.Add(match.Groups[].Value);
}
segment.ValueNames = valueNames.ToArray();
segment.Regex = new Regex(strPatten, RegexOptions.Compiled | RegexOptions.IgnoreCase);
this._pathSegmentLists.Add(segment);
}
}
}
} public DomainRoute(string domainName, string routeUrl, string physicalFile)
: this(domainName, routeUrl, physicalFile, false, new RouteValueDictionary(), new RouteValueDictionary())
{ }
#endregion #region 属性
/// <summary>
/// 泛域名
/// </summary>
public string DomainName
{
get { return this._domainName; }
set { this._domainName = value; }
}
/// <summary>
/// 映射的物理文件
/// </summary>
public string PhysicalFile
{
get { return this._physicalFile; }
set { this._physicalFile = value; }
}
/// <summary>
/// Url路由
/// </summary>
public string RouteUrl
{
get { return this._routeUrl; }
set { this._routeUrl = value; }
}
#endregion #region 方法
[DebuggerStepThrough]
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
HttpRequestBase request = httpContext.Request;
if (request.Url.Host.ToLower().Contains(this._domainName))
{
string virtualPath = request.AppRelativeCurrentExecutionFilePath.Substring() + request.PathInfo;
IList<string> segmentUrl = SplitUrlToPathSegmentStrings(virtualPath);
if (segmentUrl.Count == this._segmentCount)
{
PathSegment pathSegment = null;
string path = null;
bool isOK = true;
for (int i = ; i < this._pathSegmentLists.Count; i++)
{
pathSegment = this._pathSegmentLists[i];
path = segmentUrl[pathSegment.Index];
if (!pathSegment.Regex.IsMatch(path))
{
isOK = false;
break;
}
}
if (isOK)
{
result = new RouteData(this, new PageRouteHandler(this._physicalFile, this._checkPhysicalUrlAccess));
result.Values.Add("Domain", this._domainName);
Match match = null;
for (int i = ; i < this._pathSegmentLists.Count; i++)
{
pathSegment = this._pathSegmentLists[i];
path = segmentUrl[pathSegment.Index];
match = pathSegment.Regex.Match(path);
if (pathSegment.ValueNames.Length + == match.Groups.Count)
{
for (int j = ; j < pathSegment.ValueNames.Length; j++)
{
result.Values.Add(pathSegment.ValueNames[j], match.Groups[j + ].Value);
}
}
}
}
}
segmentUrl.Clear();
segmentUrl = null;
}
return result;
} public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return new VirtualPathData(this, this._physicalFile);
} private static IList<string> SplitUrlToPathSegmentStrings(string url)
{
List<string> list = new List<string>();
if (!string.IsNullOrEmpty(url))
{
int index;
for (int i = ; i < url.Length; i = index + )
{
index = url.IndexOf('/', i);
if (index == -)
{
string str = url.Substring(i);
if (str.Length > )
{
list.Add(str);
}
return list;
}
string item = url.Substring(i, index - i);
if (item.Length > )
{
list.Add(item);
}
//list.Add("/");
}
}
list.TrimExcess();
return list;
}
#endregion #region 内部类
private class PathSegment
{
public int Index { get; set; }
public Regex Regex { get; set; }
public string[] ValueNames { get; set; }
}
#endregion
}

添加路由:

RouteTable.Routes.Add(new DomainRoute(urlRoutingSetting.DomainName, urlRoutingSetting.RouteUrl, urlRoutingSetting.PhysicalFile, urlRoutingSetting.CheckPhysicalUrlAccess, urlRoutingSetting.Defaults, constraints));

UrlRouting原理笔记的更多相关文章

  1. 多线程之CountDownLatch的用法及原理笔记

    前言-CountDownLatch是什么? CountDownLatch是具有synchronized机制的一个工具,目的是让一个或者多个线程等待,直到其他线程的一系列操作完成. CountDownL ...

  2. 磁盘文件I/O,SSD结构,局部性原理 笔记

    磁盘文件I/O过程 进程向内核发起read scene.dat请求: 内核根据inode获取对应该进程的address space,在address space查找page_cache,如果没有找到, ...

  3. Http协议工作特点和工作原理笔记

    工作特点: (1)B/S结构(Browser/Server,浏览器/服务器模式) (2)无状态 (3)简单快速.可使用超文本传输协议.灵活运行传输各种类型 工作原理: 客户端发送请求浏览器 -> ...

  4. vuex原理笔记

    本文总结自: https://tech.meituan.com/vuex-code-analysis.html, 将要点提炼为笔记,以便不时之需,安不忘危. 核心可分为两部分: 1.vue.use(V ...

  5. MOOC 编译原理笔记(一):编译原理概述以及程序设计语言的定义

    编译原理概述 什么是编译程序 编译程序指:把某一种高级语言程序等价地转换成另一张低级语言程序(如汇编语言或机器代码)的程序. 高级语言程序-翻译->机器语言程序-运行->结果. 其中编译程 ...

  6. 机器学习之主成分分析PCA原理笔记

    1.    相关背景 在许多领域的研究与应用中,通常需要对含有多个变量的数据进行观测,收集大量数据后进行分析寻找规律.多变量大数据集无疑会为研究和应用提供丰富的信息,但是也在一定程度上增加了数据采集的 ...

  7. 学习Elasticsearch原理笔记

    Elasticsearch是一个分布式可拓展的实时搜索和分析引擎 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索 实时分析的分布式搜索引擎 可以拓展到上百台服务器,处理PB级别的结构化或 ...

  8. Kafka原理笔记

    1.什么是kafka? Kafka是一种分布式的,基于发布/订阅的消息系统(消息队列). 2.为什么要用kafka? 当业务逻辑变得复杂,数据量也会越来越多.此时可能需要增加多条数据线,每条数据线将收 ...

  9. BootStrap栅格系统原理 笔记

    1.内容居中:效果 关键代码: <div class="container"> .........之前上面添加在body标签下的代码 </div>添加cla ...

随机推荐

  1. Excel日历控件实现下拉选取日期含VB代码实现

    以下是Excel2016通过安装控件,实现表格下拉选择日期的一些步骤: 知识准备工作:先了解下如何安装控件,这一部分很重要,excel选择可用宏https://jingyan.baidu.com/ar ...

  2. 重构与模式 (Joshua Kerievsky 著)

    第1章 本书的写作缘由 第2章 重构 第3章 模式 第4章 代码坏味 第5章 模式导向的重构目录 第6章 创建 第7章 简化 第8章 泛化 第9章 保护 第10章 聚集操作 第11章 实用重构 参考文 ...

  3. (十九)golang--函数参数的传递方式

    两种传递方式: 值传递:值类型参数默认 引用传递:引用类型参数默认 一般来说,地址传递效率高,因为数据量小. 值类型:int.float.bool.string.数组.结构体: 引用类型:指针.切片. ...

  4. 解决office365无法登录以及同步的问题

    解决office365无法登录以及同步的问题 You better need to test them one by one. You better need to test them one by ...

  5. 原生js实现append()方法

    一.在使用jquery时,append() 方法在被选元素的结尾(仍然在内部)插入指定内容 使用方法:$(selector).append(content),content为必需的.规定要插入的内容( ...

  6. RoadMap:如何创建产品路线图

    (1)什么是Roadmap? RoadMap/产品路线图 Roadmap通常翻译为“路线图”或“蓝图”,目前并没有一个公认的定义.在这里,我们认为Roadmap是产品经理进行产品管理的一个中长期规划, ...

  7. redis延迟队列

    异步消息队列 Redis 的 list(列表) 数据结构常用来作为异步消息队列使用,使用rpush/lpush操作入队列, 使用 lpop 和 rpop 来出队列. > rpush notify ...

  8. Python platform 模块

    Python platform 模块 platform 模块用于查看当前操作系统的信息,来采集系统版本位数计算机类型名称内核等一系列信息. 使用方法: import platform # 获取操作系统 ...

  9. Spring Cloud Hystrix Dashboard熔断器-Turbine集群监控(六)

    序言 上一篇说啦hystrix的使用方法与配置还有工作流程及为何存在,我去,上一篇这么屌,去看看吧,没这么屌的话,我贴的有官方文档,好好仔细看看 hystrix除啦基本的熔断器功能之外,还可以对接口的 ...

  10. Python-函数参数类型及排序问题

    Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为    位置参数和关 ...