欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Asp.net Core MVC(四)

程序员文章站 2023-01-26 19:56:50
上一篇说的是asp.net mvc核心UseMvc的过程,末尾想捋一下asp.net核心的路由流转过程,现在看来还是要准备下一个代码,熟悉了代码,那么整个流转过程就通了〜 不多说,今儿先看下,RouteContext: private RouteData _routeData; public Rou ......

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

 

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

 

Asp.net Core MVC(四)