实现路由的RouterMiddleware中间件
实现路由的RouterMiddleware中间件
虽然ASP.NET Core应用的路由是通过RouterMiddleware这个中间件来完成的,但是具体的路由解析功能都落在指定的Router对象上,不过我们依然有必要以代码实现的角度来介绍一下这个中间件。在这之前,我们先来认识一个特殊的特性。[本文已经同步到《ASP.NET Core框架揭秘》之中]
让RouterMiddleware中间件委托Router完整整个路由工作之后,解析出来的路由参数会以一个RouteData对象的形式存储在RouteContext上下文中。但是RouteContext是为Router的执行建立的上下文,路由解析工作完成之后,这个上下文的生命周期也随着结束,既然整个RouteContext上下文都不存在了,请求处理的后续步骤如何获取这个RouteData对象呢?
通过《注册URL模式与HttpHandler的映射关系》的实例演示我们知道可以调用HttpContext的扩展方法GetRouteData来获取这个包含素所有路由参数的RouteData对象,这个意味着原本依附于RouteContext上下文的RouteData最终会被附加到代表当前请求上下文的HttpContext上,而具体承载这个RouteData的就是这个名为RoutingFeature的特性。RoutingFeature是我们对所有实现了IRoutingFeature接口的所有类型以及对应对象的统称。如下面的代码片段所示,这个接口通过属性RouteData来保存最终附加到HttpContext的RouteData。RoutingFeature类是这个接口的默认实现者,我们的RouterMiddleware默认情况下就是使用这个对象。
1: public interface IRoutingFeature
2: {
3: RouteData RouteData { get; set; }
4: }
5:
6: public class RoutingFeature : IRoutingFeature
7: {
8: public RouteData RouteData { get; set; }
9: }
如下所示的代码片段体现了RouterMiddleware处理请求的完整逻辑。我们在创建一个RouterMiddleware对象的时候需要指定一个Router对象,以及一个用来创建Logger的LoggerFactory。当这个中间件开始处理请求的时候,它会根据当前HttpContext创建一个RouteContext上下文对象,并将其作为参数调用Router的RotueAsync方法进行路由解析。如果在路由解析结束之后通过RouteContext的Handler属性返回的请求处理存在,意味着当前请求与注册的路由匹配,在此情况下它会将当前请求交给这个处理器做后续处理。在这之前它会从RouteContext上下文中提出出RouteData,然后据此创建一个RoutingFeature对象并附加到HttpContext上面。
1: public class RouterMiddleware
2: {
3: private ILogger _logger;
4: private RequestDelegate _next;
5: private IRouter _router;
6:
7: public RouterMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IRouter router)
8: {
9: _next = next;
10: _logger = loggerFactory.CreateLogger<RouterMiddleware>();
11: _router = router;
12: }
13:
14: public async Task Invoke(HttpContext context)
15: {
16: RouteContext routeContext = new RouteContext(context);
17: routeContext.RouteData.Routers.Add(_router);
18: await _router.RouteAsync(routeContext);
19: if (null == routeContext.Handler)
20: {
21: _logger.LogDebug(1, "Request did not match any routes.");
22: await _next(context);
23: }
24: else
25: {
26: context.Features.Set<IRoutingFeature>(new RoutingFeature { RouteData = routeContext.RouteData})
27: await routeContext.Handler(context);
28: }
29: }
30: }
我们除了可以调用HttpContext的扩展方法GetRouteData得到封装了路由参数的RouteData对象之前,我们还可以调用另一个名为GetRouteValue发的扩展方法直接获取某个路由参数的值。在如下所示的代码片段中,我们采用比较简单代码展示了这两个扩展放的实现。
1: public static class RoutingHttpContextExtensions
2: {
3: public static RouteData GetRouteData(this HttpContext context)
4: {
5: return context.Features.Get<IRoutingFeature>()?.RouteData;
6: }
7:
8: public static object GetRouteValue(this HttpContext context, string key)
9: {
10: return context.GetRouteData()?.Values[key];
11: }
12: }
一般来说我们倾向于调用ApplicationBuilder的扩展方法UseRouter来注册RouterMiddleware中间件。具体来说,我们可以选择如下两个UseRouter方法重载。如果调用第一个重载,我们需要为注册的RouterMiddleware中间件提供一个具体的Router对象。对于第二个重载来说,这个Router对象实际上是利用RouteBuilder创建的,我们在调用这个方法的时候需要以Action<IRouteBuilder>对象的形式利用这个RouteBuilder注册所需的路由。
1: public static class RoutingBuilderExtensions
2: {
3: public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, IRouter router)
4: {
5: return builder.UseMiddleware<RouterMiddleware>(new object[] { router });
6: }
7:
8: public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, Action<IRouteBuilder> action)
9: {
10: RouteBuilder routeBuilder = new RouteBuilder(builder);
11: action(routeBuilder);
12: return builder.UseRouter(routeBuilder.Build());
13: }
14: }
ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系
ASP.NET Core的路由[2]:路由系统的核心对象——Router
ASP.NET Core的路由[3]:Router的创建者——RouteBuilder
ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件
ASP.NET Core的路由[5]:内联路由约束的检验
实现路由的RouterMiddleware中间件的更多相关文章
- ASP.NET Core的路由[4]:来认识一下实现路由的RouterMiddleware中间件
虽然ASP.NET Core应用的路由是通过RouterMiddleware这个中间件来完成的,但是具体的路由解析功能都落在指定的Router对象上,不过我们依然有必要以代码实现的角度来介绍一下这个中 ...
- ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...
- ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介
概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...
- Django进阶(路由系统、中间件、缓存、Cookie和Session、Ajax发送数据
路由系统 1.每个路由规则对应一个view中的函数 url(r'^index/(\d*)', views.index), url(r'^manage/(?P<name>\w*)/(?P&l ...
- node路由访问,中间件返回数据
node路由访问,中间件返回数据 定义一个变量存放json数据,中间件接受数据 var responseData; router.use(function(req, res, next) { resp ...
- NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
NET Core 1.1 静态文件.路由.自定义中间件.身份验证简介 概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要 ...
- laravel的路由分组,中间件,命名空间,子域名,路由前缀
laravel的路由分组,就是把一些具有相同特征的路由进行分组,比如一些路由需要进行验证,一些路由有共同的前缀,一些路由有相同的控制器命名空间等. 这样把路由组合在一起,方便管理,维护性更好. Rou ...
- laravel在路由中设置中间件
//单个 路由 Route::get( 'admin/admin/index' , [ 'middleware' => 'old', 'uses' => 'Admin\AdminContr ...
- ASP.NET Core的路由[5]:内联路由约束的检验
当某个请求能够被成功路由的前提是它满足某个Route对象设置的路由规则,具体来说,当前请求的URL不仅需要满足路由模板体现的路径模式,请求还需要满足Route对象的所有约束.路由系统采用IRouteC ...
随机推荐
- Android 数据库SQLite 写入SD卡
如果手机没有root,数据库文件是无法查看到的,不方便调试. 最好的办法是把数据库写进SD卡. 修改的地方有两处: 1.在你的helper类中把数据库文件名称 DATABASE_NAME 由原来的一个 ...
- Android实现欢迎界面,点击进入应用
在主线程中开启一个新线程,每隔100ms检查一下时间是否到达自己预设的显示时间,到达则进入应用 实现屏幕的触摸事件,当触摸的时候,进入应用 package com.example.administra ...
- 2.2 CMMI2级——项目计划(Project Planning)
大家都明白这样的一个道理:做事情要有计划,有一个不成熟的计划总比没有计划要好,软件开发这么复杂的活动,更加需要计划.那么应该怎样做好一个计划呢? 如果对项目的范围.规模.性质.任务.工作量.费用等都不 ...
- 用wget扒站时遇到电信劫持
今天用wget扒下来一个html template的站. 挂在自己机器上后随便点什么,都出电信广告.仔细检查,我勒个去... 扒站过程中,刚好被电信打了劫,看看它给我下载下来的bootstrap.mi ...
- 摆脱npm的网络问题: 淘宝npm镜像
在使用npm install的时候, 经常会因为网络问题, 各种安装不顺利, 一个字'烦躁'. 自从遇上淘宝npm之后,执行cnpm install之后, 怎一个'快'字了得. 闲话不多说, 直接上干 ...
- python class对象转换成json/字典
# -*- encoding: UTF-8 -*- class Student: name = '' age = 0 def __init__(self, name, age): self.name ...
- (一)半小时开发一个APP
[前言] HPP是什么? HybirdApp的简称,详细介绍参见:HPP--让所有中小企业拥有自己的APP 说白了就是用html+css+js开发app,包括ios和android版本. HBuild ...
- 【redis使用全解析】常见运维操作
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.1 启动 1.1.1 启动redis $ redis-server redis.conf 常见选项: ./r ...
- [转]六款值得推荐的android(安卓)开源框架简介
本文转自:http://www.jb51.net/article/51052.htm .volley 项目地址 https://github.com/smanikandan14/Volley-demo ...
- [转]How do I use variables in Oracle SQL Developer?
本文转自:http://stackoverflow.com/questions/5653423/how-do-i-use-variables-in-oracle-sql-developer Below ...