• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >ASP.NET > 详解ASP.NET Core MVC 源码学习:Routing 路由

详解ASP.NET Core MVC 源码学习:Routing 路由

作者:Savorboard 字体:[增加 减小] 来源:互联网 时间:2017-05-11

Savorboard通过本文主要向大家介绍了详解ASP.NET Core MVC 源码学习:Routing 路由等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧。

路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下路由系统,ASP.NET Core 的路由系统相对于以前的 Mvc 变化很大,它重新整合了 Web Api 和 MVC。

路由源码地址 :Routing-dev_jb51.rar

路由(Routing)功能介绍

路由是 MVC 的一个重要组成部分,它主要负责将接收到的 Http 请求映射到具体的一个路由处理程序上,在MVC 中也就是说路由到具体的某个 Controller 的 Action 上。

路由的启动方式是在ASP.NET Core MVC 应用程序启动的时候作为一个中间件来启动的,详细信息会在下一篇的文章中给出。

通俗的来说就是,路由从请求的 URL 地址中提取信息,然后根据这些信息进行匹配,从而映射到具体的处理程序上,因此路由是基于URL构建的一个中间件框架。
 路由还有一个作用是生成响应的的URL,也就是说生成一个链接地址可以进行重定向或者链接。

路由中间件主要包含以下几个部分:

  1. URL 匹配
  2. URL 生成
  3. IRouter 接口
  4. 路由模板
  5. 模板约束

Getting Started

ASP.NET Core Routing 主要分为两个项目,分别是 Microsoft.AspNetCore.Routing.Abstractions,Microsoft.AspNetCore.Routing。前者是一个路由提供各功能的抽象,后者是具体实现。

我们在阅读源码的过程中,我建议还是先大致浏览一下项目结构,然后找出关键类,再由入口程序进行阅读。

Microsoft.AspNetCore.Routing.Abstractions

大致看完整个结构之后,我可能发现了几个关键的接口,理解了这几个接口的作用后能够帮助我们在后续的阅读中事半功倍。

IRouter

在 Microsoft.AspNetCore.Routing.Abstractions 中有一个关键的接口就是 IRouter:

public interface IRouter
{
 Task RouteAsync(RouteContext context);

 VirtualPathData GetVirtualPath(VirtualPathContext context);
}
</div>

这个接口主要干两件事情,第一件是根据路由上下文来进行路由处理,第二件是根据虚拟路径上下文获取 VirtualPathData。

IRouteHandler

另外一个关键接口是 IRouteHandler , 根据名字可以看出主要是对路由处理程序机型抽象以及定义的一个接口。

public interface IRouteHandler
{
 RequestDelegate GetRequestHandler(HttpContext httpContext, RouteData routeData);
}
</div>

它返回一个 RequestDelegate 的一个委托,这个委托可能大家比较熟悉了,封装了处理Http请求的方法,位于Microsoft.AspNetCore.Http.Abstractions 中,看过我之前博客的同学应该比较了解。

这个接口中 GetRequestHandler 方法有两个参数,第一个是 HttpContext,就不多说了,主要是来看一下第二个参数 RouteData。

RouteData,封装了当前路由中的数据信息,它包含三个主要属性,分别是 DataTokens, Routers, Values。

DataTokens: 是匹配的路径中附带的一些相关属性的键值对字典。

Routers: 是一个 Ilist<IRouter> 列表,说明RouteData 中可能会包含子路由。

Values: 当前路由的路径下包含的键值。

还有一个 RouteValueDictionary, 它是一个集合类,主要是用来存放路由中的一些数据信息的,没有直接使用 IEnumerable<KeyValuePair<string, string>> 这个数据结构是应为它的内部存储转换比较复杂,它的构造函数接收一个 Object 的对象,它会尝试将Object 对象转化为自己可以识别的集合。

IRoutingFeature

我根据这个接口的命名一眼就看出来了这个接口的用途,还记得我在之前博客中讲述Http管道流程中得时候提到过一个叫 工具箱 的东西么,这个 IRoutingFeature 也是其中的一个组成部分。我们看一下它的定义:

public interface IRoutingFeature
{
 RouteData RouteData { get; set; }
}
</div>

原来他只是包装了 RouteData,到 HttpContext 中啊。

IRouteConstraint

这个接口我在阅读的时候看了一下注释,原来路由中的参数参数检查主要是靠这个接口来完成的。

我们都知道在我们写一个 Route Url地址表达式的时候,有时候会这样写:Route("/Product/{ProductId:long}") , 在这个表达式中有一个 {ProductId:long} 的参数约束,那么它的主要功能实现就是靠这个接口来完成的。

/// Defines the contract that a class must implement in order to check whether a URL parameter
/// value is valid for a constraint.
public interface IRouteConstraint
{
 bool Match(
  HttpContext httpContext,
  IRouter route,
  string routeKey,
  RouteValueDictionary values,
  RouteDirection routeDirection);
}
</div>

Microsoft.AspNetCore.Routing

Microsoft.AspNetCore.Routing 主要是对 Abstractions 的一个主要实现,我们阅读代码的时候可以从它的入口开始阅读。

RoutingServiceCollectionExtensions 是一个扩展ASP.NET Core DI 的一个扩展类,在这个方法中用来进行 ConfigService,Routing 对外暴露了一个 IRoutingBuilder 接口用来让用户添加自己的路由规则,我们来看一下:

public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, Action<IRouteBuilder> action)
{
 //...略
 
 // 构造一个RouterBuilder 提供给action委托宫配置
 var routeBuilder = new RouteBuilder(builder);
 action(routeBuilder);
 
 //调用下面的一个扩展方法,routeBuilder.Build() 见下文
 return builder.UseRouter(routeBuilder.Build());
}

public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, IRouter router)
{
  //...略
  
 return builder.UseMiddleware<RouterMiddleware>(router);
}

</div>

routeBuilder.Build() 构建了一个集合 RouteCollection,用来保存所有的 IRouter 处理程序信息,包括用户配置的Router。

RouteCollection 本身也实现了 IRouter , 所以它也具有路由处理的能力。

Routing 中间件的入口是 RouterMiddleware 这个类,通过这个中间件注册到 Http 的管道处理流程中, ASP.NET Core MVC 会把它默认的作为其配置项的一部分,当然你也可以把Routing单独拿出来使用。

我们来看一下 Invoke 方法里面做了什么,它位于RouterMiddleware.cs 文件中。

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);
  }
}

</div>

首先,通过 httpContext 来初始化路由上下文(RouteContext),然后把用户配置的路由规则添加到路由上下文RouteData中的Routers中去。

接下来 await _router.RouteAsync(context) , 就是用到了 IRouter 接口中的 RouteAsync 方法了。

我们接着跟踪 RouteAsync 这个函数,看其内部都做了什么? 我们又跟踪到了RouteCollection.cs 这个类:

我们看一下 RouteAsync 的流程:

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);

      if (context.Handler != null)
      {
        break;



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2018-08-20Razor TagHelper实现Markdown转HTML的方法
  • 2017-05-11LINQ字符串向datetime 转换时失败的处理方法
  • 2017-05-11ASP.NET服务器控件的生命周期分析
  • 2017-05-11.net清空所有Cache的实现代码
  • 2017-05-11asp.net中一次性动态绑定多个droplistdown
  • 2017-05-11asp.net cookie的操作,写入、读取与操作
  • 2017-05-11ASP.NET中常用的用来输出JS脚本的类
  • 2017-05-11asp.net数据验证控件
  • 2017-05-11灵活掌握Asp.net MVC中GridView的使用方法
  • 2017-05-11微信扫码支付(PC端)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Asp.net的应用程序对象和页面生存周期
    • 禁用aspx页面的客户端缓存(防止页面被修改)
    • 详细介绍.NET中的动态编译技术
    • Visual Studio 2015 配置 Opencv3.2的图文详解
    • asp.net 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。
    • 实现Asp.net mvc上传头像加剪裁功能
    • asp.net显示自己的网页图标的几种方式
    • asp.net Linq to Xml学习笔记
    • asp.net微信开发(已关注用户管理)
    • Datalist控件使用存储过程来分页实现代码

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有