MVC路由机制(转)
今天我来缕一下MVC的路由机制,因为使用MVC已经快一年了,之前也只是上手,没有系统去理会。项目完了,结合实际使用,回过头来深入一下。
MVC 学习索引(点击即可)
一个请求进入IIS后

传统ASP.NET 路由部分
1、IIS根据文件类型将请求转交给相应的处理程序,如果属于ASP.NET文件,则将请求转发给aspnet_isapi.dll。(注:在II6和IIS7上的处理方式是有区别的)
2、 HTTP处理模块UrlRoutingModule接收到请求后,循环调用其RouteCollection集合中的RouteBase对象,找出匹配的RouteBase。
3、根据匹配的RouteBase对象返回的RoueData对象,获取RouteHandler。
4、RouteHandler返回一个HTTP处理程序(IHttpHandler),最终通过此处理程序处理请求,生成应答内容。
5.、如果RouteHandler为MvcRouteHandler,并且其返回的HTTP处理程序为MvcHandler,则进入到MVC框架,MvcHandler对象负责调用适当的控制器和活动方法,生成应答内容。
MVC 路由部分

关键类说明
1、UrlRoutingModule类
此类事路由系统的核心类,其主要功能是根据请求上下文找出合适的RouteBase对象。属性RouteCollection是一个RouteBase对象集合,UrlRoutingModule接收到请求后,循环RouteCollection集合中的RouteBase对象,调用其GetRouteData方法,如果该方法返回的RouteData对象不为null,则终止循环,将RouteData对象存入RequestContext。然后根据RouteData的RouteHandler获取合适的IHttpHandler处理程序。
UrlRoutingModule实际上是一个ASP.NET的HTTP 处理模块,所以它通过配置文件的<httpMoudles>配置节点来添加的。
2、RouteTable类
用于存储应用程序的路由集合,静态属性Routes返回应用程序的路由集合,它实际等同于UrlRoutingModule的RouteCollection属性。通过RouteTable.Routes.Add方法可以添加自定义的RouteBase对象。
3、RouteBase类
表示一个ASP.NET路由的基类[System.Web.Routing],所有的路由都应该继承自此类。

GetRouteData方法检查传入的HttpContextBase信息是否符合路由规则,符合则返回一个RouteData对象,不符合则返回null,此方法由UrlRoutingModule类在循环RouteTable.Routes集合时调用。
GetVirtualPath方法根据路由数据生成相应的Url。
4、Route类
是RouteBase的一个实现,主要添加了几个属性:
Constraints: 对URL的约束条件
DataTokens:传递到路由处理程序的自定义值
Defaults:Url不包含指定参数时得默认值
RouteHandler:一个路由处理程序(IRouteHandler)
5、IRouteHandler接口
路由处理程序接口,包含一个GetHttpHandler方法,用于返回一个IHttpHandler处理程序对象。
6、MvcRouteHandler类
Mvc框架实现的一个路由处理程序,其GetHttpHandler方法返回一个MvcHandler对象
- #region IRouteHandler Members
- IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
- return GetHttpHandler(requestContext);
- }
- #endregion
7、MvcHandler
由MvcRouteHandler返回,根据请求信息,调用合适的控制器和方法,生成应答内容。
- public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState {
- private static readonly object _processRequestTag = new object();
- private ControllerBuilder _controllerBuilder;
- internal static readonly string MvcVersion = GetMvcVersionString();
- public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";
- public MvcHandler(RequestContext requestContext) {
- if (requestContext == null) {
- throw new ArgumentNullException("requestContext");
- }
- RequestContext = requestContext;
- }
- internal ControllerBuilder ControllerBuilder {
- get {
- if (_controllerBuilder == null) {
- _controllerBuilder = ControllerBuilder.Current;
- }
- return _controllerBuilder;
- }
- set {
- _controllerBuilder = value;
- }
- }
- public static bool DisableMvcResponseHeader {
- get;
- set;
- }
- protected virtual bool IsReusable {
- get {
- return false;
- }
- }
- public RequestContext RequestContext {
- get;
- private set;
- }
- protected internal virtual void AddVersionHeader(HttpContextBase httpContext) {
- if (!DisableMvcResponseHeader) {
- httpContext.Response.AppendHeader(MvcVersionHeaderName, MvcVersion);
- }
- }
- protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state) {
- HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);
- return BeginProcessRequest(iHttpContext, callback, state);
- }
- protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state) {
- return SecurityUtil.ProcessInApplicationTrust(() => {
- IController controller;
- IControllerFactory factory;
- ProcessRequestInit(httpContext, out controller, out factory);
- IAsyncController asyncController = controller as IAsyncController;
- if (asyncController != null) {
- // asynchronous controller
- BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
- try {
- return asyncController.BeginExecute(RequestContext, asyncCallback, asyncState);
- }
- catch {
- factory.ReleaseController(asyncController);
- throw;
- }
- };
- EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult) {
- try {
- asyncController.EndExecute(asyncResult);
- }
- finally {
- factory.ReleaseController(asyncController);
- }
- };
- SynchronizationContext syncContext = SynchronizationContextUtil.GetSynchronizationContext();
- AsyncCallback newCallback = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, syncContext);
- return AsyncResultWrapper.Begin(newCallback, state, beginDelegate, endDelegate, _processRequestTag);
- }
- else {
- // synchronous controller
- Action action = delegate {
- try {
- controller.Execute(RequestContext);
- }
- finally {
- factory.ReleaseController(controller);
- }
- };
- return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
- }
- });
- }
- protected internal virtual void EndProcessRequest(IAsyncResult asyncResult) {
- SecurityUtil.ProcessInApplicationTrust(() => {
- AsyncResultWrapper.End(asyncResult, _processRequestTag);
- });
- }
- private static string GetMvcVersionString() {
- // DevDiv 216459:
- // This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in
- // medium trust. However, Assembly.FullName *is* accessible in medium trust.
- return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2);
- }
- protected virtual void ProcessRequest(HttpContext httpContext) {
- HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);
- ProcessRequest(iHttpContext);
- }
- protected internal virtual void ProcessRequest(HttpContextBase httpContext) {
- SecurityUtil.ProcessInApplicationTrust(() => {
- IController controller;
- IControllerFactory factory;
- ProcessRequestInit(httpContext, out controller, out factory);
- try {
- controller.Execute(RequestContext);
- }
- finally {
- factory.ReleaseController(controller);
- }
- });
- }
- private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) {
- // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks
- // at Request.Form) to work correctly without triggering full validation.
- bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current);
- if (isRequestValidationEnabled == true) {
- ValidationUtility.EnableDynamicValidation(HttpContext.Current);
- }
- AddVersionHeader(httpContext);
- RemoveOptionalRoutingParameters();
- // Get the controller type
- string controllerName = RequestContext.RouteData.GetRequiredString("controller");
- // Instantiate the controller and call Execute
- factory = ControllerBuilder.GetControllerFactory();
- controller = factory.CreateController(RequestContext, controllerName);
- if (controller == null) {
- throw new InvalidOperationException(
- String.Format(
- CultureInfo.CurrentCulture,
- MvcResources.ControllerBuilder_FactoryReturnedNull,
- factory.GetType(),
- controllerName));
- }
- }
- private void RemoveOptionalRoutingParameters() {
- RouteValueDictionary rvd = RequestContext.RouteData.Values;
- // Get all keys for which the corresponding value is 'Optional'.
- // ToArray() necessary so that we don't manipulate the dictionary while enumerating.
- string[] matchingKeys = (from entry in rvd
- where entry.Value == UrlParameter.Optional
- select entry.Key).ToArray();
- foreach (string key in matchingKeys) {
- rvd.Remove(key);
- }
- }
- #region IHttpHandler Members
- bool IHttpHandler.IsReusable {
- get {
- return IsReusable;
- }
- }
- void IHttpHandler.ProcessRequest(HttpContext httpContext) {
- ProcessRequest(httpContext);
- }
- #endregion
- #region IHttpAsyncHandler Members
- IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
- return BeginProcessRequest(context, cb, extraData);
- }
- void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) {
- EndProcessRequest(result);
- }
- #endregion
- }
值得一提的是,在MVC3中已经实现异步处理(IHttpAsyncHandler)
8、StopRoutingHandler类
表示一个“不处理URL的路由处理类”, 比如MVC在RouteCollection类型上扩展了一个IgnoreRoute方法,用于指示路由系统忽略处理指定的url。其实现方式是生成一个Route对象,指定其RouteHandler属性为一个StopRoutingHandler对象。
9、IRouteConstraint接口
用于构建Route.Constraints属性,表示一个约束条件。Match方法用于检查url是否符合路由规则,符合返回true,否则false。
MVC路由机制(转)的更多相关文章
- WebApi-1 与MVC路由机制比较
在MVC里面,默认路由机制是通过url路径去匹配对应的action方法 public class RouteConfig { public static void RegisterRoutes(Rou ...
- MVC路由机制
按照传统,在很多Web框架中(如经典的ASP.JSP.PHP.ASP.NET等之类的框架),URL代表的是磁盘上的物理文件.例如,当看到请求http://example.com/albums/li ...
- asp.net MVC 路由机制
1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...
- asp.net MVC 路由机制 Route
1:ASP.NET的路由机制主要有两种用途: -->1:匹配请求的Url,将这些请求映射到控制器 -->2:选择一个匹配的路由,构造出一个Url 2:ASP.NET路由机制与URL重写的区 ...
- Asp.net MVC路由机制
C:/Windows/Microsoft.NET/Framwork/v4.0.30319/config/web.config-> httpModules-> System.Web.Rout ...
- C# 通过反射实现类似MVC路由的机制
最近封装了个功能非常类似于MVC的路由.//MVC路由机制先找到Controller Action 什么是反射 反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获 得.NET ...
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗?
前言:从MVC到WebApi,路由机制一直是伴随着这些技术的一个重要组成部分. 它可以很简单:如果你仅仅只需要会用一些简单的路由,如/Home/Index,那么你只需要配置一个默认路由就能简单搞定: ...
- 【C#】 WebApi 路由机制剖析
C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转自:https://blog.csdn.net/wulex/article/details/71601478 2017年05月11日 10 ...
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转载https://www.cnblogs.com/landeanfen/p/5501490.html
阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...
随机推荐
- X86 寻址方式、AT&T 汇编语言相关知识、AT&T 与 Intel 汇编语言的比较、gcc 嵌入式汇编
注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...
- Python中的迭代和可迭代对象
什么是迭代(iteration)呢? 给定一个list或者tuple,通过for循环来遍历这个list或者tuple.这种遍历就是迭代(iteration).只要是可迭代的对象都可以进行迭代.怎么判断 ...
- python标准库介绍——13 types 模块详解
== types 模块== ``types`` 模块包含了标准解释器定义的所有类型的类型对象, 如 [Example 1-86 #eg-1-86] 所示. 同一类型的所有对象共享一个类型对象. 你可以 ...
- 机器学习 Top 20 Python 开源项目
转自:http://mp.weixin.qq.com/s?__biz=MzA4MjEyNTA5Mw==&mid=2652565022&idx=1&sn=9aa035097120 ...
- spineRunTime for cocos2dx v3 中动画播完删除animation
spineRunTime for cocos2dx v3 中删除animation,发现下面写法会崩溃: spine::SkeletonAnimation* animationNode = spi ...
- unity3D角色代码控制问题
///////////////2015/07/06//////// ///////////////by xbw////////////// //////////////环境 unity4.6.1// ...
- JS动态增加删除UL节点LI
JS如何动态增加删除UL节点LI及相关内容. <ul id="ul"> <li id=1>11111111111111111<a href=" ...
- 每日英语:Genetic Manipulation Extends Life of Mice 20%
By reducing the activity of one type of gene, scientists said they increased the average life span o ...
- 随笔记:Python于Windows下初实践,及使用Connector/Python连接MySQL
有一同事要离职了,我负责交接一个用Python同步数据的项目. 之前木有做过Python,周休,做个简单的查询数据库,小练一下手. 包含: 安装 连接.查询MySQL 列表 元组 for循环 whil ...
- JQuery中eq()和get()的区别
众所周知,eq()方法返回的是一个JQuery对象,也就是[object Object]; get()方法返回的是DOM对象组成的数组,也就是[object HTMLLIElement]; 我们用一个 ...