分享

Asp.net Core MVC(四)

 小样样样样样样 2020-04-15

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

 

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

 

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多