自定义Modue与Hander

之前讲了管道流中的Module与Hndler。现在我们可以去自定义Module和Handler

Module

其实很简单,一共需要三个步骤

  • 定义一个类去继承IHttpModule。并实现接口,这里推荐类以Module结尾
  • 在Init方法中注册我们所需要的事件,完成拦截器。
  • 在WebConfig的System.webServer节点中配置Modules


Handler

和自定义Module类似

  • 创建一个类去继承IHttpHandler接口,并实现接口。
  • 在ProcessRequest中进行做我们需要的处理
  • 在WebConfig的system.webServer节点中配置hanlder

注:MVC也是这么去做的,注册了Mvc的Module和Mvc的Handler。

MVC管道

MVC的路由也是通过Module去拦截,然后找到匹配的路由。然后拿到handler激活Controller。下面解析一下过程

在MVC中我们在RouteConfig中配置路由。结构是这样的

那么截获它的是UrlRoutingModule =>

=> 这个moudule如我们自定义的一样,继承了IHttpModule。注册了事件 application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);。需要说明的 是,这里也有了缓存。只有第一次才会去执行

=> RouteData routeData = this.RouteCollection.GetRouteData(context); 映入眼帘的是这段代码。GetRouterData就是去获取匹配的路由

=> 然后看到了一个foreach,是的。foreach。按照我的观察,它是一个键值对。这里就知道了,为什么常用的路由要放到前面。可以快速遍历到。这里的值是RouteBase,它是一个抽象类。具体的实现应该在子类里面。

=> 继续会看到,获取了RouteHandler!。那么RouteHandler是什么呢。

=> 转到了MapRoute也就是我们的定义路由方法,看到了一个MvcRouteHandler。再转到Route的构造函数

=> 可以看到他是一个IRouteHandler的实现!之前Module的图继续往下走,看到了调用了GetHttpHandler这个方法。可以看到其实它就相当于一个工厂。那么拿到的又是什么呢

=> 可以发现,返回了一个MvcHandler。它就是我们的最终主角。这时候一系列操作就完成了,MvcHandler的ProcessRequest方法,下图是同步方法,这里拿到了IController。然后再Execute。 IController是ControllerBase类继承的接口,Execute中又调用了ExecuteCore方法。也就是Controller类的实现。到此管道结束

这张图就是MVC的管道整体流程


Route详解

我们在定义了MapRoute后,到底放到了什么地方呢?又是怎么对值进行过滤的呢?道兄莫慌,下面一一分析。

注意,这里并没有实践。因为断点一直下不去。所以引用了别人的图。待之后再实践吧

上图不难发现,除了MapRoute外还有IngoreRoute。 进入到Blobal中可以看到注册路由用的是RouteTable.Routes

RouteTable

=> Routes [RouteCollection]

先看MapRoute的创建

先是创建一个Route然后添加到了我们的 routes [RouteCollection]中

Route route = new Route(url, new MvcRouteHandler()) {

Defaults = CreateRouteValueDictionaryUncached(defaults),

Constraints = CreateRouteValueDictionaryUncached(constraints),

DataTokens = new RouteValueDictionary()

};

ConstraintValidation.Validate(route);

if ((namespaces != null) && (namespaces.Length > 0))

{

route.DataTokens["Namespaces"] = namespaces;

}

routes.Add(name, route);

然后再去看IgnoreRoute的创建

是的没错。这里创建一个IgnoreRouteInternal,然后也添加到了Routes中。

IgnoreRouteInternal route = new IgnoreRouteInternal(url) {

Constraints = CreateRouteValueDictionaryUncached(constraints)

};

ConstraintValidation.Validate(route);

routes.Add(route);

那么问题来了,MVC是如何分别受支持和不被支持的路由呢?

还记得,我们的Route的构造函数需要一个IRouteHandler。这个IgnoreRouteInternal则是Route的子类,那么它传入的是什么呢?

可以看到,是StopRoutingHandler,这就不难猜到了。回到UrlRoutingModule代码中,从下图可以发现,这里拿到了RouteHandler之后,进行了判断。如果是StopRoutingHandler则直接把请示打回去。


下面开始说参数验证,

MapRoute有几个重载,有这样一个参数,contraints。它可以对我们的参数进行一些约束。

一个简单的玩法,这里对id这个参数进行了约束,使其必须是数字。不仅是id,其它的片段也可以进行约束。

看一下源码,其实这个方法就是进行匹配。在ProcessConstraion中,拿到了IRouteConstrraint。如果我们的表达式是strng,就进行正则匹配。

上面有一个Match。这个是最吊的自定义。


进行自定义约束玩玩

  • 需要继承自IRouteConstraint接口,并实现
  • 在MapRoute对参数进行传入约束实例

MVC5-2 MVC的管道流与路由的更多相关文章

  1. MVC5-1 ASP.NET的管道流

    MVC5 和WebForm的区别 WebForm是一个Page贯穿了一个.CS代码. 1对1 = 耦合在一起 MVC在Controller中将 bihind和page进行了分离. 多对多 = 松耦合 ...

  2. ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)

    在上一篇"ASP.NET MVC请求处理管道生命周期的19个关键环节(7-12) ",体验了7-12关键环节,本篇继续. ⒀当请求到达UrlRoutingModule的时候,Url ...

  3. mvc请求管道(一)

    一.前言 在平常做后台开发的时候,经常会说到请求管道,很多开发者都知道这个,也能说几句,可能没法详细的去介绍,今天就来详细的说一下这个. 二.到达IIS之前 请看下面这个流程图.从用户打开浏览器到请求 ...

  4. ASP.NET MVC请求处理管道生命周期的19个关键环节(7-12)

    在上一篇"ASP.NET MVC请求处理管道生命周期的19个关键环节(1-6) ",体验了1-6关键环节,本篇继续. ⑦根据IsapiWorkerRequest对象,HttpRun ...

  5. 跟我学ASP.NET MVC之十一:URL路由

    摘要: 在MVC框架之前,ASP.NET假定在请求的URLs和服务器硬盘文件之间有直接的关系.服务器的职责是接收浏览器请求,从相应的文件发送输出. 这种方法只能工作于Web表单,每一个ASPX页面既是 ...

  6. Java IO7:管道流、对象流

    前言 前面的文章主要讲了文件字符输入流FileWriter.文件字符输出流FileReader.文件字节输出流FileOutputStream.文件字节输入流FileInputStream,这些都是常 ...

  7. ASP.NET MVC请求处理管道生命周期的19个关键环节(1-6)

    ASP.NET和ASP.NET MVC的HttpApplication请求处理管道有共同的部分和不同之处,本系列将体验ASP.NET MVC请求处理管道生命周期的19个关键环节. ①以IIS6.0为例 ...

  8. JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码

    一.对象序列化 1.1.对象序列化 被操作的对象需要实现Serializable接口 1.2.对象序列化流ObjectOutputStream与ObjectInputStream ObjectInpu ...

  9. Java管道流

    管道流的主要作用可以用于两个线程之间的通信,有管道输出流 PipeOutputStream和管道输入流 PipeInputStream.然后通过connect将两个管道连接起来. import jav ...

随机推荐

  1. Messenger

    Messenger Mvvm提倡View和ViewModel的分离,View只负责数据的显示,业务逻辑都尽可能放到ViewModel中, 保持View.xaml.cs中的简洁(没有任何代码,除了构造函 ...

  2. 【分布式协调器】Paxos的工程实现-cocklebur简介(一)

    初识分布式协调器 分布式协调器的“协调”二字让人摸不到头脑,怎么就协调了,用的着协调吗?实际上这个东西在之前就是为了提供分布式锁服务而设计的,伟大的google公司发明了chubby,雅虎随后也推出了 ...

  3. hibernate Expression详解

    关键字: hibernate expression hibernate Expression详解Expression.gt:对应SQL条件中的"field > value " ...

  4. .NET Core VS Code 环境配置

    VSCode .NET环境配置     在此之前我一直是使用notepad++配置的C/C#环境来写代码,比起打开"笨重"的VS要方便很多.VSCode出来之后,本来也想折腾了一下 ...

  5. jQuery Ajax 处理 HttpStatus

    今天同事碰到一个问题:当服务端Session失效后用ajax请求数据,页面端无法提示和执行跳转.我最先想到是,在后端用js输出一个跳转.发现输出没有效果,因为ajax是异步请求, 需要在success ...

  6. vNext之旅(1):从概念和基础开始

    ASP.NET vNext or .NET vNext? vNext在曝光以来绝大多数以ASP.NET vNext这样的的字眼出现,为什么这边会提及.NET vNext?原因是我认为ASP.NET只是 ...

  7. dig 常用的域名查询工具

    dig 命令是常用的域名查询工具,可以用来测试域名系统工作是否正常. 语法: dig (选项) (参数) 选项: @<服务器地址>: 指定进行域名解析的域名服务器: -b: 当主机具有多个 ...

  8. killall 根据名称终止进程

    根据名称终止进程 killall [option] name-list killall 将信号发送到一个或多个进程用来终止它.除超级用户外,只有进程的所有者才可以对进程执行killall,超级用户可以 ...

  9. [转]oracle学习入门系列之五内存结构、数据库结构、进程

    原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...

  10. Activity has leaked window that was originally added -界面退出时未关闭对话框异常 android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? -

    退出Activity时弹出登录框,点击确定finish当前Activity,结果报了这个错,随后查找资料知道 原因: 是因为退出Activity时没有关闭弹出框,出现了这个错误 解决方法: 只需要在a ...