上一篇说的是asp.net mvc核心UseMvc的过程,末尾想捋一下asp.net核心的路由流转过程,现在看来还是要准备下一个代码,熟悉了代码,那么整个流转过程就通了〜
不多说,今儿先看下,RouteContext:
private RouteData _routeData; public RouteContext(HttpContext httpContext) { HttpContext = httpContext; RouteData = new RouteData(); } public RequestDelegate Handler { get; set; } public HttpContext HttpContext { get; } public RouteData RouteData { get { return _routeData; } set { if (value == null) { throw new ArgumentNullException(nameof(RouteData)); } _routeData = value; } }
这里可以理解RouteContext(路由子网)就是路由的环境。
其中包含三个属性器,RouteData,RequestDelegate与HttpContext。
那么什么时候设置路由的某些呢呢?
个人理解是,实在端端执行委托时,根据我们设置的路由处理程序来设置路先来看下RouteData,
private RouteValueDictionary _dataTokens; private List<IRouter> _routers; private RouteValueDictionary _values; public RouteValueDictionary DataTokens { get { if (_dataTokens == null) { _dataTokens = new RouteValueDictionary(); } return _dataTokens; } } public IList<IRouter> Routers { get { if (_routers == null) { _routers = new List<IRouter>(); } return _routers; } } public RouteValueDictionary Values { get { if (_values == null) { _values = new RouteValueDictionary(); } return _values; } }
继续分解来看。
RouteValueDictionary DataTokens自定义传值,但不参与路由匹配。
RouteValueDictionary Values 匹配路由中的参数。
以上两者的区别在于是否参与匹配路由中的参数
RouteValueDictionary继承自IDictionary,IReadOnlyDictionary。
IList <IRouter>路由器:是参与成功匹配请求的路由的列表。
Route类作业IRouter接口的实现,使用路由模板的语法定义模式,在调用RouteAsync时匹配的URL路径。调用GetVirtualPath时,Route使用同一路由模板生成访问路径。换句话说,Route时Asp.Net Core的核心创造者。
继续往下翻代码route.cs:
public string RouteTemplate => ParsedTemplate.TemplateText; protected override Task OnRouteMatched(RouteContext context) { context.RouteData.Routers.Add(_target); return _target.RouteAsync(context); } protected override VirtualPathData OnVirtualPathGenerated(VirtualPathContext context) { return _target.GetVirtualPath(context); }
OnRouteMatched方法,我们在创建路由对象时,需要建立一个路由器对象,通过该方法后,重新写入RouteData的Routers属性中 RouteData的Routers属性中,然后执行 RouteAsync方法。
public virtual Task RouteAsync(RouteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } EnsureMatcher(); EnsureLoggers(context.HttpContext); var requestPath = context.HttpContext.Request.Path; if (!_matcher.TryMatch(requestPath, context.RouteData.Values)) { // If we got back a null value set, that means the URI did not match return Task.CompletedTask; } // Perf: Avoid accessing dictionaries if you don't need to write to them, these dictionaries are all // created lazily. if (DataTokens.Count > 0) { MergeValues(context.RouteData.DataTokens, DataTokens); } if (!RouteConstraintMatcher.Match( Constraints, context.RouteData.Values, context.HttpContext, this, RouteDirection.IncomingRequest, _constraintLogger)) { return Task.CompletedTask; } _logger.RequestMatchedRoute(Name, ParsedTemplate.TemplateText); return OnRouteMatched(context); }
private void EnsureMatcher() { if (_matcher == null) { _matcher = new TemplateMatcher(ParsedTemplate, Defaults); } }
TemplateM atcher类暂时不做过多的说明,只要知道时分析路径并匹配
RouteTemplate。(后续再看)
看到这里终于看到点路由相关的东西,通过RouteAsync我们1>确定路径与路由规则匹配; 2>通过路由模板匹配路径上的参数。
下面我们再看OnVirtualPathGenerated这个方法。
public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureBinder(context.HttpContext); EnsureLoggers(context.HttpContext); var values = _binder.GetValues(context.AmbientValues, context.Values); if (values == null) { // We're missing one of the required values for this route. return null; } if (!RouteConstraintMatcher.Match( Constraints, values.CombinedValues, context.HttpContext, this, RouteDirection.UrlGeneration, _constraintLogger)) { return null; } context.Values = values.CombinedValues; var pathData = OnVirtualPathGenerated(context); if (pathData != null) { // If the target generates a value then that can short circuit. return pathData; } // If we can produce a value go ahead and do it, the caller can check context.IsBound // to see if the values were validated. // When we still cannot produce a value, this should return null. var virtualPath = _binder.BindValues(values.AcceptedValues); if (virtualPath == null) { return null; } pathData = new VirtualPathData(this, virtualPath); if (DataTokens != null) { foreach (var dataToken in DataTokens) { pathData.DataTokens.Add(dataToken.Key, dataToken.Value); } } return pathData; }
方法GetVirtualPath的返回增量VirtualPathData(后续补充),
只需要知道VirtualPathData类,包含路径与虚拟路径的参考信息,也就是若要生成URL,请调用GetVirtualPath方法。该方法返回VirtualPathData类的实例,该类包含有关路由的信息。VirtualPath属性包含生成的URL。
身体不太舒服,先写到这里,下篇继续看这篇未解释的代码。