上一篇说的是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 RouteData RouteData { { return _routeData; } if (value == null) { throw ArgumentNullException(nameof(RouteData)); } _routeData = value; } }
这里可以理解RouteContext(路由子网)就是路由的环境。
其中包含三个属性器,RouteData,RequestDelegate与HttpContext。
那么什么时候设置路由的某些呢呢?
个人理解是,实在端端执行委托时,根据我们设置的路由处理程序来设置路先来看下RouteData,
RouteValueDictionary _dataTokens; private List<IRouter> _routers; RouteValueDictionary _values; RouteValueDictionary DataTokens { if (_dataTokens == ) { _dataTokens = RouteValueDictionary(); } _dataTokens; } } public IList<IRouter> Routers { if (_routers == ) { _routers = new List<IRouter>(); } _routers; } } RouteValueDictionary Values { if (_values == ) { _values = RouteValueDictionary(); } _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); _target.RouteAsync(context); } VirtualPathData OnVirtualPathGenerated(VirtualPathContext context) { _target.GetVirtualPath(context); }
OnRouteMatched方法,我们在创建路由对象时,需要建立一个路由器对象,通过该方法后,重新写入RouteData的Routers属性中 RouteData的Routers属性中,然后执行 RouteAsync方法。
virtual Task RouteAsync(RouteContext context) { if (context == ) { 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 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); } RouteConstraintMatcher.Match( Constraints,context.RouteData.Values,context.HttpContext,this,RouteDirection.IncomingRequest,_constraintLogger)) { Task.CompletedTask; } _logger.RequestMatchedRoute(Name,ParsedTemplate.TemplateText); OnRouteMatched(context); }
private void EnsureMatcher() { if (_matcher == ) { _matcher = TemplateMatcher(ParsedTemplate,Defaults); } }
TemplateM atcher类暂时不做过多的说明,只要知道时分析路径并匹配
RouteTemplate。(后续再看)
看到这里终于看到点路由相关的东西,通过RouteAsync我们1>确定路径与路由规则匹配; 2>通过路由模板匹配路径上的参数。
下面我们再看OnVirtualPathGenerated这个方法。
VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureBinder(context.HttpContext); EnsureLoggers(context.HttpContext); var values = _binder.GetValues(context.AmbientValues,context.Values); if (values == We're missing one of the required values for this route. return ; } ; } context.Values = values.CombinedValues; var pathData = OnVirtualPathGenerated(context); if (pathData != If the target generates a value then that can short circuit. 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 == ; } pathData = new VirtualPathData(if (DataTokens != foreach (var dataToken in DataTokens) { pathData.DataTokens.Add(dataToken.Key,dataToken.Value); } } pathData; }
方法GetVirtualPath的返回增量VirtualPathData(后续补充),
只需要知道VirtualPathData类,包含路径与虚拟路径的参考信息,也就是若要生成URL,请调用GetVirtualPath方法。该方法返回VirtualPathData类的实例,该类包含有关路由的信息。VirtualPath属性包含生成的URL。
身体不太舒服,先写到这里,下篇继续看这篇未解释的代码。