上一篇說的是asp.net mvc核心UseMvc的過程,末尾想捋一下asp.net核心的路由流轉過程,如今看來仍是要準備下一個代碼,熟悉了代碼,那麼整個流轉過程就通了〜html
很少說,今兒先看下,RouteContext:mvc
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(路由子網)就是路由的環境。asp.net
其中包含三個屬性器,RouteData,RequestDelegate與HttpContext。ide
那麼何時設置路由的某些呢呢?ui
我的理解是,實在端端執行委託時,根據咱們設置的路由處理程序來設置路先來看下RouteData,this
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; } }
繼續分解來看。spa
RouteValueDictionary DataTokens自定義傳值,但不參與路由匹配。.net
RouteValueDictionary Values 匹配路由中的參數。code
以上二者的區別在因而否參與匹配路由中的參數router
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。
身體不太舒服,先寫到這裏,下篇繼續看這篇未解釋的代碼。
原文出處:https://www.cnblogs.com/xtt321/p/12420958.html