我们来看IRouteBuilder的定义:

    public interface IRouteBuilder
{
IRouter DefaultHandler { get; set; } IServiceProvider ServiceProvider { get; } IList<IRouter> Routes { get; } IRouter Build();
}

一个默认的IRouter对象,一个Build方法,一个IRouter集合和一个获取服务对象IServiceProvider。

我们进一步看IRouteBuilder的实现RouterBuilder:

public class RouteBuilder : IRouteBuilder
{
public RouteBuilder()
{
Routes = new List<IRouter>();
} public IRouter DefaultHandler { get; set; } public IServiceProvider ServiceProvider { get; set; } public IList<IRouter> Routes
{
get;
private set;
} public IRouter Build()
{
var routeCollection = new RouteCollection(); foreach (var route in Routes)
{
routeCollection.Add(route);
} return routeCollection;
}
}

主要的实现是Build方法,这个方法的实现也很简单,遍历Routes向一个实现了IRouter接口的RouteCollection对象添加IRouter,我们可以先看一下RouteCollection的实现:

public class RouteCollection : IRouteCollection
{
private readonly List<IRouter> _routes = new List<IRouter>();
private readonly List<IRouter> _unnamedRoutes = new List<IRouter>();
private readonly Dictionary<string, INamedRouter> _namedRoutes =
new Dictionary<string, INamedRouter>(StringComparer.OrdinalIgnoreCase); private RouteOptions _options; public IRouter this[int index]
{
get { return _routes[index]; }
} public int Count
{
get { return _routes.Count; }
} public void Add([NotNull] IRouter router)
{
var namedRouter = router as INamedRouter;
if (namedRouter != null)
{
if (!string.IsNullOrEmpty(namedRouter.Name))
{
_namedRoutes.Add(namedRouter.Name, namedRouter);
}
}
else
{
_unnamedRoutes.Add(router);
} _routes.Add(router);
} public async virtual Task RouteAsync(RouteContext context)
{
for (var i = ; i < Count; i++)
{
var route = this[i]; var oldRouteData = context.RouteData; var newRouteData = new RouteData(oldRouteData);
newRouteData.Routers.Add(route); try
{
context.RouteData = newRouteData; await route.RouteAsync(context);
if (context.IsHandled)
{
break;
}
}
finally
{
if (!context.IsHandled)
{
context.RouteData = oldRouteData;
}
}
}
} public virtual VirtualPathData GetVirtualPath(VirtualPathContext context)
{
EnsureOptions(context.Context); // If we're using Best-Effort link generation then it means that we'll first look for a route where
// the route values are validated (context.IsBound == true). If we can't find a match like that, then
// we'll return the path from the first route to return one.
var useBestEffort = _options.UseBestEffortLinkGeneration; if (!string.IsNullOrEmpty(context.RouteName))
{
var isValidated = false;
VirtualPathData bestPathData = null;
INamedRouter matchedNamedRoute;
if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute))
{
bestPathData = matchedNamedRoute.GetVirtualPath(context);
isValidated = context.IsBound;
} // If we get here and context.IsBound == true, then we know we have a match, we want to keep
// iterating to see if we have multiple matches.
foreach (var unnamedRoute in _unnamedRoutes)
{
// reset because we're sharing the context
context.IsBound = false; var pathData = unnamedRoute.GetVirtualPath(context);
if (pathData == null)
{
continue;
} if (bestPathData != null)
{
// There was already a previous route which matched the name.
throw new InvalidOperationException(
Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName));
}
else if (context.IsBound)
{
// This is the first 'validated' match that we've found.
bestPathData = pathData;
isValidated = true;
}
else
{
Debug.Assert(bestPathData == null); // This is the first 'unvalidated' match that we've found.
bestPathData = pathData;
isValidated = false;
}
} if (isValidated || useBestEffort)
{
context.IsBound = isValidated; if (bestPathData != null)
{
bestPathData = new VirtualPathData(
bestPathData.Router,
NormalizeVirtualPath(bestPathData.VirtualPath),
bestPathData.DataTokens);
} return bestPathData;
}
else
{
return null;
}
}
else
{
VirtualPathData bestPathData = null;
for (var i = ; i < Count; i++)
{
var route = this[i]; var pathData = route.GetVirtualPath(context);
if (pathData == null)
{
continue;
} if (context.IsBound)
{
// This route has validated route values, short circuit.
return new VirtualPathData(
pathData.Router,
NormalizeVirtualPath(pathData.VirtualPath),
pathData.DataTokens);
}
else if (bestPathData == null)
{
// The values aren't validated, but this is the best we've seen so far
bestPathData = pathData;
}
} if (useBestEffort)
{
return new VirtualPathData(
bestPathData.Router,
NormalizeVirtualPath(bestPathData.VirtualPath),
bestPathData.DataTokens);
}
else
{
return null;
}
}
} private PathString NormalizeVirtualPath(PathString path)
{
var url = path.Value; if (!string.IsNullOrEmpty(url) && _options.LowercaseUrls)
{
var indexOfSeparator = url.IndexOfAny(new char[] { '?', '#' }); // No query string, lowercase the url
if (indexOfSeparator == -)
{
url = url.ToLowerInvariant();
}
else
{
var lowercaseUrl = url.Substring(, indexOfSeparator).ToLowerInvariant();
var queryString = url.Substring(indexOfSeparator); // queryString will contain the delimiter ? or # as the first character, so it's safe to append.
url = lowercaseUrl + queryString;
} return new PathString(url);
} return path;
} private void EnsureOptions(HttpContext context)
{
if (_options == null)
{
_options = context.RequestServices.GetRequiredService<IOptions<RouteOptions>>().Options;
}
}
}

乍一看这个类的功能还是比较庞大的,我们主要关注他对IRouter接口签名的实现:

Task RouteAsync(RouteContext context):

通过代码我们可以看到,这个方法主要对RouteCollection本身持有的Route 规则循环添加到路由上下文RouteContext.RouteData中。

VirtualPathData GetVirtualPath(VirtualPathContext context):

												

ASP.NET MVC 源码分析(二) —— 从 IRouteBuilder认识路由构建的更多相关文章

  1. asp.net mvc源码分析-ModelValidatorProviders 客户端的验证

    几年写过asp.net mvc源码分析-ModelValidatorProviders 当时主要是考虑mvc的流程对,客户端的验证也只是简单的提及了一下,现在我们来仔细看一下客户端的验证. 如图所示, ...

  2. ASP.NET MVC源码分析

    MVC4 源码分析(Visual studio 2012/2013) HttpModule中重要的UrlRoutingModule 9:this.OnApplicationPostResolveReq ...

  3. asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证

    原文:asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证 在前面的文章中我们曾经涉及到ControllerActionInvoker类GetPara ...

  4. ASP.NET MVC 源码分析(一)

    ASP.NET MVC 源码分析(一) 直接上图: 我们先来看Core的设计: 从项目结构来看,asp.net.mvc.core有以下目录: ActionConstraints:action限制相关 ...

  5. asp.net MVC 源码分析

    先上一张图吧 asp.net请求机制的图  by传智播客邹华栋老师 然后是 邹老师添加MVC请求过程的图 其实MVC 是在.netframework上加了一个过滤器  HttpModule 在C:\W ...

  6. asp.net mvc源码分析-Route的GetRouteData

    我知道Route这里东西应该算路由,这里把它放到mvc里面有些不怎么合适,但是我想大家多数遇到路由都是在mvc的时候吧.首先我们还是来看看GetRouteData方法吧 [csharp] public ...

  7. asp.net mvc源码分析-Action篇 IModelBinder

    我们首先还是看看ReflectedParameterBindingInfo的Binder属性吧: public override IModelBinder Binder {            ge ...

  8. ASP.NET MVC源码分析系列

    Controller下的JsonResult的ExecuteResult方法 public override void ExecuteResult(ControllerContext context) ...

  9. ASP.NET WebForm / MVC 源码分析

    浏览器 Url:https//localhost:6565/Home/Index ,https//localhost:6565/WebForm1.aspx,请求服务器(构建请求报文,并且将请求报文发送 ...

随机推荐

  1. js模拟复制

    现在浏览器种类也越来越多,诸如 IE.Firefox.Chrome.Safari等等,因此现在要实现一个js复制内容到剪贴板的小功能就不是一件那么容易的事了.   一.实现点击按钮,复制文本框中的的内 ...

  2. 洛谷P1731生日蛋糕(dfs+剪枝)

    P1731 生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M)层蛋糕是半径为R ...

  3. codevs2147数星星(哈希)

    2147 数星星  时间限制: 3 s  空间限制: 64000 KB  题目等级 : 钻石 Diamond   题目描述 Description 小明是一名天文爱好者,他喜欢晚上看星星.这天,他从淘 ...

  4. [Swift通天遁地]九、拔剑吧-(12)创建Preview-Transition图像预览界面

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  5. printf的字符型

    参  数 说  明 %s 按实际宽度输出一个字符串 %ms m指定宽度(不足时左补空格,大于时按实际宽度输出) %-ms 左对齐,不足时右补空格 %m.ns 输出占m个字符位置,其中字符数最多n个,左 ...

  6. python自动化学习笔记3-集合、函数、模块

    文件操作 上次学习到文件的读写,为了高效的读写文件,我们可以用循环的方式,一行一行的进行读写操作,打开文件的方法是open的方法,打开文件执行完后还要进行关闭操作. 一般的文件流操作都包含缓冲机制,w ...

  7. Android基础TOP4:Tost的使用

    Activity: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xm ...

  8. html5——web存储

    基本概念 1.传统方式我们以document.cookie来进行存储的,但是由于其存储大小只有4k左右,并且解析也相当的复杂,给开发带来诸多不便 2.h5存储设置.读取方便,而且容量较大,sessio ...

  9. SQL基本操作——HAVING

    HAVING:在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与合计函数一起使用. 我们拥有下面这个 "Orders" 表: O_Id OrderDate Or ...

  10. ZfNet解卷积:可视化CNN模型( PythonCode可视化Cifar10)

    原文链接:caffe Model的可视化 snapshot: 6000       一个在线可视化小工具:http://blog.csdn.net/10km/article/details/52713 ...