• asp.net core mvc 中间件之路由


    asp.net core mvc 中间件之路由

    路由中间件

    • 首先看路由中间件的源码
    • 先用httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合
    • 然后把路由上下文作为参数,调用IRouter.RouteAsync方法,该方法主要是进行路由匹配,匹配成功后给context.Handler赋值
    • 如果路由匹配成功,且handler不为空,说明已经有了后续处理消息的通道,就不用走下一个中间件了,否则消息处理交给下一个中间件
    • MVC流程就是从这里开始,路由匹配成功后,从handler进入MVC流程
    
    namespace Microsoft.AspNetCore.Builder
    {
        public class RouterMiddleware
        {
            private readonly ILogger _logger;
            private readonly RequestDelegate _next;
            private readonly IRouter _router;
    
            public RouterMiddleware(
                RequestDelegate next,
                ILoggerFactory loggerFactory,
                IRouter router)
            {
                _next = next;
                _router = router;
    
                _logger = loggerFactory.CreateLogger<RouterMiddleware>();
            }
    
            public async Task Invoke(HttpContext httpContext)
            {
                var context = new RouteContext(httpContext);
                context.RouteData.Routers.Add(_router);
    
                await _router.RouteAsync(context);
    
                if (context.Handler == null)
                {
                    _logger.RequestDidNotMatchRoutes();
                    await _next.Invoke(httpContext);
                }
                else
                {
                    httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature()
                    {
                        RouteData = context.RouteData,
                    };
    
                    await context.Handler(context.HttpContext);
                }
            }
        }
    }
    

    路由

    • IRouter接口仅定义了两个方法,其中路由的核心在于RouteAsync方法,该方法可用于路由匹配,返回处理委托
    • RouteBase抽象类的的RouteAsync方法进行路由的匹配,Route类的RouteAsync方法仅仅是执行了构造函数传进来的routeBuilder.DefaultHandler路由的RouteAsync方法,DefaultHandler实际上也是继承自IRouter
    • RouteHandlerMvcRouteHandler都可以作为routeBuilder.DefaultHandler,以提供Route类实例化需要的参数。RouteHandlerRouteAsync方法直接给context.Handler赋值从构造函数接收到的委托。
    • MvcRouteHandler``RouteAsync方法则先根据匹配到的路由从已注册的控制器中适配方法,然后得到actionDescriptor,包含http上下文以及方法的基本信息,最后直接给context.Handler赋值,MVC流程从invoker.InvokeAsync()开始
            public Task RouteAsync(RouteContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }
    
                var candidates = _actionSelector.SelectCandidates(context);
                if (candidates == null || candidates.Count == 0)
                {
                    _logger.NoActionsMatched(context.RouteData.Values);
                    return Task.CompletedTask;
                }
    
                var actionDescriptor = _actionSelector.SelectBestCandidate(context, candidates);
                if (actionDescriptor == null)
                {
                    _logger.NoActionsMatched(context.RouteData.Values);
                    return Task.CompletedTask;
                }
    
                context.Handler = (c) =>
                {
                    var routeData = c.GetRouteData();
    
                    var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor);
                    if (_actionContextAccessor != null)
                    {
                        _actionContextAccessor.ActionContext = actionContext;
                    }
    
                    var invoker = _actionInvokerFactory.CreateInvoker(actionContext);
                    if (invoker == null)
                    {
                        throw new InvalidOperationException(
                            Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(
                                actionDescriptor.DisplayName));
                    }
    
                    return invoker.InvokeAsync();
                };
    
                return Task.CompletedTask;
            }
    

    路由注册

    • 最常见的注册方法
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
    

    总结

    • 路由实际上就是根据请求链接,遍历路由模板进行匹配,匹配到了返回一个Handler用于后续处理消息
    • 其中的匹配过程,除了模板匹配,还要进行方法匹配,最后才进入业务处理流程
    • 总的来说,路由中间件就是调用IRouter实例的RouteAsync方法,得到Handler的话就执行,否则处理权交给下一个中间件。而路由实现,主要是匹配过程以及返回Handler。到这里,就可以发散思维,做各种有趣的事了
    • 以上是关于路由的知识梳理,看不懂没关系,这很正常,直接能看懂才怪了,进过实践,代码调试,都不能完全理解这个过程,而静下心来总结的时候,往往就能将零碎的知识点串联起来,打成一片,扫除盲点
      持续更新,原文地址:https://www.cnblogs.com/xxred/p/9582200.html
  • 相关阅读:
    1132: 零起点学算法39——多组测试数据(a+b)
    1131: 零起点学算法38——求阶乘和
    1130: 零起点学算法37——求阶乘
    1129: 零起点学算法36——3n+1问题
    1128: 零起点学算法35——再求多项式(含浮点)
    1127: 零起点学算法34——继续求多项式
    1126: 零起点学算法33——求多项式
    Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化
    Netty源码分析(前言, 概述及目录)
    基于HTK语音工具包进行孤立词识别的使用教程
  • 原文地址:https://www.cnblogs.com/xxred/p/9582200.html
Copyright © 2020-2023  润新知