.NET/ASP.NET MVC Controller 控制器(一:深入解析控制器运行原理)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

阅读目录:

  • 1.开篇介绍

  • 2.ASP.NETMVC Controller 控制器的入口(Controller的执行流程)

  • 3.ASP.NETMVC Controller 控制器的入口(Controller的继承体系)

  • 4.ASP.NETMVC IController Factory 控制器工厂(Controller的创建)

1】开篇介绍

经过前一篇文章.NET/ASP.NET Routing路由(深入解析路由系统架构原理) 的讲解,我们对ASP.NETRouting路由系统的整个运行机制有了一个基本的了解;当我们能清楚的知道Url是如何被解析成RouteData对象时,下面就是这些路由数据是如何被后面的应用框架所使用的,而通往应用框架的入口是MvcRouteHandler对象;

这篇文章将继续讲解通过路由后的ASP.NETMVC Controller控制器是如何被加载、激活并且执行的;跟控制器相关的一套对象模型是被MvcHandler对象作为源头调用起来的,也就是说,当我们穿过UrlRoutingModule对象后,并且成功的获取到应用框架配置的路由数据后,下面将进入IHttpHandler接口,而这个接口真是我们初始化RouteData对象时设定的应用框架入口,ASP.NETMVC所使用的是MvcHandler对象;

MvcRouteHandler对象是UrlRoutingModuleMvcHandler对象的连接器,只有MvcRouteHandler对象能成功执行后,方能进入到MvcHandler对象中,后续的一切运转才能顺利执行;

2】ASP.NETMVC Controller 控制器的入口(Controller的执行流程)

在系统刚启动的时候,也就是在Global.asax.cs文件里面我们配置了Http客户端请求服务器的Url模板;在路由解析模块(UrlRoutingModule)里面,它将通过字符串级别的操作,解析出我们Url模板中的{Controller}/{Action}等的占位符变量;所以这个时候Controller的概念对我们来说还只是一个字符串而已,而到了目前的这个Controller控制器解析的位置其实已经和路由基本没关系了,因为我们穿过了路由模块到达了Controller解析的环节;Controller解析已经属于ASP.NETMVC应用框架的范围,我们可以简单的将路由解析(UrlRoutingModule)的过程视为将请求的Url(含有数据的Url)与我们配置的Url模板进行模式匹配的过程,得出匹配后的Url数据(RouteData),然后将Url数据并且连同当前请求上下文一起封装成RequestContext对象(RouteData、HttpContextBase)传入到Controller解析的环节,也就是MvcHandler中,作为MvcHandler构造函数的参数;

当MvcHandler接管控制权之后它需要准备好对Controller的解析和执行,但是Controller并发一个简单的对象,它有一个复杂的继承体系和使用方式,原因在于它需要协调多方面的工作所以变的有很复杂;

根据MVC的架构模式理论便知道Controller是协调Model与View的中间纽带,它既要管理好Model的执行,也要管理好View的呈现;而原本MVC的架构模式提出的背景是在WinFrom的情况下,也就是传统C/S结构的系统;WinFrom结构的系统有一个好处就是它的执行很方便,从View的展现收集数据到Controller的调度执行Model会容易完成,但是ASP.NETMVC是建立在ASP.NET WEB背景之下的MVC模式框架,所以这个时候对Controller的激活会变的相当麻烦,因为在传输过程中Controller已经是字符串形式,如果是在C/S结构中那么Controller对于每次处理一样的View不会每次都进行激活;既然每次都需要激活就需要进行缓存策略,缓存策略只是Controller中的一个关键点,需要明白的是Controller的确需要做很多事情;

图1:

140954800.jpg

根据上图的执行顺序,能看出Controller控制器扮演着一个很重要的角色,所有的执行、返回值、视图呈现均需要通过它来管理调度;当然本章的重点是搞清楚此图中的第一环节,Controller是如何被加载激活的,这里面将涉及到众多的辅助对象模型,比如:ControllerFactory控制器工厂,而控制器工厂又将借助ControllerTypeCache来缓存Controller对象,而ConrollerTypeCache又将借助TypeCacheSerializer来对Controller缓存文件的序列化;

3.ASP.NETMVC Controller 控制器的入口(Controller的继承体系)

Controller控制器既然扮演着重要的角色,那么它就不会是一个简单的对象结构,它有着一个复杂的继承体系和对象模型支撑它来完成这些艰巨的任务;Controller要想能够运行起来,就需要搞清楚它有哪些执行入口,而需要知道它有哪些执行入口我们就需要搞清楚它的继承体系;入口的最高层抽象在哪一层,这样我们才能举一反三的扩展Controller的众多重要的功能;

首先我们了解到Controller的顶层抽象是IController接口,然后接着是ControllerBase抽象类实现了这个接口,而作为顶层抽象的实现ControllerBase完成了从IController接口继承下来的方法;

1
2
3
public  interface  IController {
     void  Execute(RequestContext requestContext);
}

通过该代码段可以看出,Controller的执行需要一个RequestContext对象,而这个对象真是UrlRoutingModule环节所完成的结果,RequestContext对象内部封装了在Request阶段所获得的请求数据,里面包括了跟Http相关的请求上下文(HttpContextBase),最重要的是路由数据对象(RouteData);而控制器的执行必须需要RouteData中的有关Controller数据对象,也就是从请求Url中通过模式匹配出来的{Controller}部分的字符串;

ControllerBase定义了Controller使用到的部分公共属性,比如:用来保存临时数据的TempData,用来返回到View中的Model数据对象ViewBag、ViewData;并且初始化了ControllerContext对象,用来作为后续Controller使用的数据容器和操作上下文;

1
2
3
protected  virtual  void  Initialize(RequestContext requestContext) {
     ControllerContext =  new  ControllerContext(requestContext,  this );
}

在ControllerBase中将对IController.Execute(RequestContext requestContext)方法调用转到了protected abstract void ExecuteCore()方法中;这是一个典型的模板方法模式,下面的继承类Controller,只需要接着protected abstract void ExecuteCore()方法就能和ControllerBase衔接上;

1
public  abstract  class  Controller : ControllerBase

Controller类继承自ControllerBase,而Controller的任务只需要完成ExecuteCore()方法;

1
2
3
4
5
6
7
8
9
10
11
12
protected  override  void  ExecuteCore() {
            PossiblyLoadTempData();
            try  {
               string  actionName = RouteData.GetRequiredString( "action" );
                if  (!ActionInvoker.InvokeAction(ControllerContext, actionName)) {
                    HandleUnknownAction(actionName);
                }
            }
            finally  {
                PossiblySaveTempData();
            }
        }

Controller.ExecuteCore()的代码将从RouteData中获取执行action的名称,然后通过一个ActionInvoke的组件进行Action的调用,当Action被执行的时候将进入到我们继承的Controller,如:HomeController:Controller中,在我们自定的Controller中的方法都将被视为Action的匹配目标之一;

图2:

141200927.jpg

根据上图的指示,ControllerBase首先是实现IController接口,完成了对Execute(RequestContext requestContext)方法的实现,然后Controller继承ControllerBase类,重写了模板方法ExecuteCore()方法,然后我们自定义的HomeController其实是Action的容器,当Controller的ExecuteCore()方法执行时将通过ActionInvoke类进行对HomeController中的方法调用;

4.ASP.NETMVC IController Factory 控制器工厂(Controller的创建)

当清楚了Controller的继承体系之后,下面回到MvcHandler调用的环节;MvcHandler继承自IHttpHandler接口 ,表示它将是ASP.NET真正执行请求处理的地方;在MvcHandler处理请求的方法中ProcessRequest(HttpContextBase httpContext),将通过IControllerFactory接口创建IController接口;

IControllerFactory接口是控制器工厂接口,专门用来实现创建IController对象工厂类,在ASP.NETMVC内部有一个实现了IControllerFactory接口的默认工厂类DefaultControllerFactory,ASP.NETMVC内部是用这个类来创建IController对象的;

1
factory = ControllerBuilder.GetControllerFactory();

获取IDefaultControllerFactory接口需要通过ControllerBuilder对象,ControllerBuilder类是专门用来管理IControllerFactory对象的,同时ControllerBuilder也是应用编程接口,让自定义IControllerFactory对象成为可能;

创建IController需要我们传入RequestContext对象和ControllerName控制器名称;

1
2
3
4
// Get the controller type
string  controllerName = RequestContext.RouteData.GetRequiredString( "controller" );
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);

从RequestContext.RouteData中获取到当前请求的conroller名称,然后用来作为factory.CreateController的参数;

图3:

141319320.jpg

MvcHandler通过ControllerBuilder对象的静态属性Current获取到ControllerBuilder对象实例,显然ControllerBuilder是一个单例模式的对象;然后通过ControllerBuilder对象获取到DefaultControllerFactory默认IControllerFactory工厂对象,接着利用DefaultControllerFactory创建出IController对象;






 本文转自 王清培 51CTO博客,原文链接:http://blog.51cto.com/wangqingpei557/1315881,如需转载请自行联系原作者
相关文章
|
3月前
|
前端开发 Java 开发者
Spring MVC中的控制器:@Controller注解全解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序控制层的核心。它不仅简化了控制器的定义,还提供了灵活的请求映射和处理机制。本文将深入探讨`@Controller`注解的用法、特点以及在实际开发中的应用。
169 0
|
5月前
|
开发框架 前端开发 .NET
VB.NET中如何利用ASP.NET进行Web开发
在VB.NET中利用ASP.NET进行Web开发是一个常见的做法,特别是在需要构建动态、交互式Web应用程序时。ASP.NET是一个由微软开发的开源Web应用程序框架,它允许开发者使用多种编程语言(包括VB.NET)来创建Web应用程序。
112 6
|
6月前
|
开发框架 .NET 开发工具
【Azure 应用服务】App Service 的.NET Version选择为.NET6,是否可以同时支持运行ASP.NET V4.8的应用呢?
【Azure 应用服务】App Service 的.NET Version选择为.NET6,是否可以同时支持运行ASP.NET V4.8的应用呢?
|
6月前
|
开发框架 JSON .NET
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
|
6月前
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
|
7月前
|
开发框架 搜索推荐 前端开发
【.NET全栈】ASP.NET开发Web应用——Web部件技术
【.NET全栈】ASP.NET开发Web应用——Web部件技术
|
8月前
|
Linux C# C++
【.NET Developer】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
本文介绍了如何使用VS2019和.NET框架创建一个Blazor应用,并将其部署到Azure应用服务。首先,Blazor是一个使用C#而非JavaScript构建交互式Web UI的框架,支持共享服务器和客户端应用逻辑,以及与Docker和Azure集成。任务包括创建Blazor项目,配置Dockerfile为Linux容器,本地测试,发布到Azure Container Registry (ACR),然后在Azure App Service for Container上部署。在部署过程中,需确保Docker设置正确,开启ACR的Admin访问权限,并监控镜像拉取和容器启动日志。
335 0
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
53 0
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多