博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
asp.net core mvc 中间件之路由
阅读量:6211 次
发布时间:2019-06-21

本文共 3949 字,大约阅读时间需要 13 分钟。

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
(); } 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。到这里,就可以发散思维,做各种有趣的事了
  • 以上是关于路由的知识梳理,看不懂没关系,这很正常,直接能看懂才怪了,进过实践,代码调试,都不能完全理解这个过程,而静下心来总结的时候,往往就能将零碎的知识点串联起来,打成一片,扫除盲点
    持续更新,原文地址:
用心做好每一件事,结果会给你最大的惊喜!

转载地址:http://uhdja.baihongyu.com/

你可能感兴趣的文章
json格式的字符串转换成json对象
查看>>
jQuery中的选择元素
查看>>
防火墙原理详解之iptables的使用
查看>>
无法获得锁 /var/lib/dpkg/lock - open (11: 资源临时不可用)解决办法
查看>>
cmd更换编码类型
查看>>
我的友情链接
查看>>
Delphi XE2 之 FireMonkey 入门(27) - 数据绑定: TBindingsList: TBindScope
查看>>
图解 CSS (5): font - 字体
查看>>
我的友情链接
查看>>
编程思维,从10^0为什么是1开始……
查看>>
C#发送消息到记事本窗口
查看>>
linux 下 apache php-cgi 安装及配置
查看>>
ArrayList/Vector/LinkedList 区别与用法
查看>>
读《head first设计模式》随笔(1
查看>>
linux之pmap命令
查看>>
mkcephfs脚本
查看>>
重置centos 7 root密码
查看>>
【移动开发】WIFI热点通信(一)
查看>>
SQL Server2008附加数据库之后显示为只读时解决方法
查看>>
Android知识体系
查看>>