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。
身体不太舒服,先写到这里,下篇继续看这篇未解释的代码。
下一篇: 网易考拉退差价流程 网易考拉如何退货退款