ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler)

本文通过一张图来看一下路由的配置以及请求处理的机制。(asp.net core 系列目录

一、概述

路由主要有两个主要功能:

  1. 将请求的url与已定义的路由进行匹配,找到该url对应的处理程序并传入该请求进行处理。
  2. 根据已定义的路由生成url

这两个功能看起来这两个是相反的。

a.路由的配置

路由的两个功能都离不开一个基本的操作:路由的基本配置。在startup中默认通过 routes.maproute(name: "default",template: "{controller=home}/{action=index}/{id?}")定义,

当然我们还可以继续 routes.maproute(。。。);  这样就定义了一系列的路由匹配方式组成一个路由表,例如这样:

app.usemvc(routes =>
{
    routes.maproute(name: "test", template: "hello");
    routes.maproute("flylolo/{code}/{name}", myroutehandler.handler);
    routes.maproute(name: "default", template: "{controller=home}/{action=index}/{id?}");
});

每一个maproute会生成一个route,第二个maproute看起来有些特殊,我们可以传入一个自定义的requestdelegate(本例为myroutehandler.handler)来处理“flylolo/{code}/{name}”这样的请求,

    public static class myroutehandler
    {
        public static async task handler(httpcontext context)
        {
            await context.response.writeasync("myroutehandler");
        }
    }

它会被封装成一个routehandler(new routehandler(myroutehandler.handler))赋值给route的target属性,而对于另外两种没有指定的,route的target属性默认会被指定为mvcroutehandler ,如下图:

b.handler的选择

当请求进入之后,根据此路由表对该url进行逐一匹配,并将请求交给匹配到的路由的target(即mvcroutehandler或routehandler),调用 _target.routeasync(context); ,在这个方法中,若是mvcroutehandler会对请求的controller和action验证,若验证成功,则对context(是一个routecontext)的handler属性赋值一个匿名方法;若是routehandler则会直接将其封装的requestdelegate(本例为myroutehandler.handler)赋值给routecontext.handler.

c.请求处理

经过handler的选择后,若routecontext.handler不为空,则调用routecontext.handler(httpcontext)对请求进行处理。

d.其他

回想一下中间件,这个是不是和app.map("/test", xxhandle)这样配置中间件的方式有点像,当请求路径是/test的时候,请求交由xxhandle处理,同样是map,对比着更容易理解。

下面通过一张图看一下路由配置和请求处理的流程。

二、流程及解析

 点击看大图

  为了方便查看,对几个“重点对象”做了颜色标识(点击图片可以看大图):

 

  1. 路由的初始化配置
  2. 一切从startup开始,之前在中间件的文章中介绍过,一般是通过多个usexxx的方式将多个中间件组成“请求处理管道”,而在这里通过usemvc方法进行配置,传入routes.maproute(...)这样的一个或多个配置。

      接下来会new一个

routebuilder

    ,顾名思义就是一个route的创建者,通过调用传进来的一个或多个routes.maproute()方法生成多个route,并配置默认的handler。
                var routes = new routebuilder(app)
                {
                    defaulthandler = app.applicationservices.getrequiredservice<mvcroutehandler>(),
                };

                configureroutes(routes);//调用startup中的routes.maproute(...)方法

 

          ①调用routebuilder的build方法,生成一个routecollection

        public irouter build()
        {
            var routecollection = new routecollection();

            foreach (var route in routes)
            {
                routecollection.add(route);
            }

            return routecollection;
        }

 

          ②routecollection实现iroutecollection和irouter接口,他是在startup中的配置组成的集合。

          ③routermiddleware就是专门用于进行路由处理的中间件,在此将routecollection作为中间件routermiddleware的参数,并将这个中间件插入管道中。

    public class routermiddleware
    {
        private readonly irouter _router; //就是routecollection

        public async task invoke(httpcontext httpcontext);

    }

 

2. 请求处理流程

      ④请求的处理流程在routermiddleware的invoke()方法中。

   ⑤请求首先会被封装成一个routecontext,本质就是将httpcontext、_router(也就是routecollection)包装到一个对象里。

  var context = new routecontext(httpcontext);
  context.routedata.routers.add(_router);
public class routecontext
{
   private routedata _routedata;
   public requestdelegate handler ;
   public httpcontext httpcontext;//简单的赋值
   public routedata routedata;
}

          ⑥调用_router(也就是routecollection)的routeasync(context)方法,在其中遍历每一个路由

          ⑦若与请求url匹配,则将对应的handler赋值给context.handler。

        public async virtual task routeasync(routecontext context)
        {
            // 快照备份
            var snapshot = context.routedata.pushstate(null, values: null, datatokens: null);
            //遍历
            for (var i = 0; i < count; i++)
            {
                var route = this[i];
                context.routedata.routers.add(route);

                try
                {
                    await route.routeasync(context);//若匹配,则给context.handler赋值

                    if (context.handler != null)
                    {
                        break;
                    }
                }
                finally
                {
                    if (context.handler == null)
                    {
                        snapshot.restore();//通过快照还原
                    }
                }
            }
        }

              ⑧在routermiddleware的invoke()方法中,调用新赋值的context.handler处理httpcontext;

httpcontext.features[typeof(iroutingfeature)] = new routingfeature()
{
    routedata = context.routedata,
};

await context.handler(context.httpcontext);

 三、其他

      由于文章写的比较早各种原因一直没有写完,现在发现2.2版本之后,启用了新的路由方案,还是把这章完成了发出来,有愿意看的可以参考一下,下一篇文章介绍一下2.2版的新的路由方案,至于通过路由生成url部分,就暂时不写了。

本文链接:https://2i3i.com/aspnetcore2_15.html ,转载请注明来源地址。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇