• Asp.net Core MVC(四)


    上一篇说的是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。

    身体不太舒服,先写到这里,下篇继续看这篇未解释的代码。

  • 相关阅读:
    LIS例题
    基数排序板子
    lower_bound和upper_bound在刷leetcode的时候...
    leetcode1081/316 求字典序最小的包含所有出现字符一次的子序列
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合 【深度优先搜索】【原创】
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合【原创】
    Spring 中注入 properties 中的值
    Java 枚举活用
    Intellij IDEA 快捷键整理(TonyCody)
    WIN API -- 2.Hello World
  • 原文地址:https://www.cnblogs.com/xtt321/p/12420958.html
Copyright © 2020-2023  润新知