zoukankan      html  css  js  c++  java
  • MVC<2:路由映射原理(写在最后)>

    MVC路由机制 (原文请点击http://blog.csdn.net/xiaoyong322/article/details/7401391

     
     

    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对象

    1. #region IRouteHandler Members 
    2.       IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) { 
    3.           return GetHttpHandler(requestContext); 
    4.       } 
    5.       #endregion 
      #region IRouteHandler Members
            IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) {
                return GetHttpHandler(requestContext);
            }
            #endregion

    7、MvcHandler

        由MvcRouteHandler返回,根据请求信息,调用合适的控制器和方法,生成应答内容。

    1. publicclass MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState { 
    2.       privatestaticreadonlyobject _processRequestTag = newobject(); 
    3.       private ControllerBuilder _controllerBuilder; 
    4.  
    5.       internalstaticreadonlystring MvcVersion = GetMvcVersionString(); 
    6.       publicstaticreadonlystring MvcVersionHeaderName = "X-AspNetMvc-Version"
    7.  
    8.       public MvcHandler(RequestContext requestContext) { 
    9.           if (requestContext == null) { 
    10.               thrownew ArgumentNullException("requestContext"); 
    11.           } 
    12.  
    13.           RequestContext = requestContext; 
    14.       } 
    15.  
    16.       internal ControllerBuilder ControllerBuilder { 
    17.           get
    18.               if (_controllerBuilder == null) { 
    19.                   _controllerBuilder = ControllerBuilder.Current; 
    20.               } 
    21.               return _controllerBuilder; 
    22.           } 
    23.           set
    24.               _controllerBuilder = value; 
    25.           } 
    26.       } 
    27.  
    28.       publicstaticbool DisableMvcResponseHeader { 
    29.           get
    30.           set
    31.       } 
    32.  
    33.       protectedvirtualbool IsReusable { 
    34.           get
    35.               returnfalse
    36.           } 
    37.       } 
    38.  
    39.       public RequestContext RequestContext { 
    40.           get
    41.           privateset
    42.       } 
    43.  
    44.       protectedinternalvirtualvoid AddVersionHeader(HttpContextBase httpContext) { 
    45.           if (!DisableMvcResponseHeader) { 
    46.               httpContext.Response.AppendHeader(MvcVersionHeaderName, MvcVersion); 
    47.           } 
    48.       } 
    49.  
    50.       protectedvirtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state) { 
    51.           HttpContextBase iHttpContext = new HttpContextWrapper(httpContext); 
    52.           return BeginProcessRequest(iHttpContext, callback, state); 
    53.       } 
    54.  
    55.       protectedinternalvirtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state) { 
    56.           return SecurityUtil.ProcessInApplicationTrust(() => { 
    57.               IController controller; 
    58.               IControllerFactory factory; 
    59.               ProcessRequestInit(httpContext, out controller, out factory); 
    60.  
    61.               IAsyncController asyncController = controller as IAsyncController; 
    62.               if (asyncController != null) { 
    63.                   // asynchronous controller 
    64.                   BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) { 
    65.                       try
    66.                           return asyncController.BeginExecute(RequestContext, asyncCallback, asyncState); 
    67.                       } 
    68.                       catch
    69.                           factory.ReleaseController(asyncController); 
    70.                           throw
    71.                       } 
    72.                   }; 
    73.  
    74.                   EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult) { 
    75.                       try
    76.                           asyncController.EndExecute(asyncResult); 
    77.                       } 
    78.                       finally
    79.                           factory.ReleaseController(asyncController); 
    80.                       } 
    81.                   }; 
    82.  
    83.                   SynchronizationContext syncContext = SynchronizationContextUtil.GetSynchronizationContext(); 
    84.                   AsyncCallback newCallback = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, syncContext); 
    85.                   return AsyncResultWrapper.Begin(newCallback, state, beginDelegate, endDelegate, _processRequestTag); 
    86.               } 
    87.               else
    88.                   // synchronous controller 
    89.                   Action action = delegate
    90.                       try
    91.                           controller.Execute(RequestContext); 
    92.                       } 
    93.                       finally
    94.                           factory.ReleaseController(controller); 
    95.                       } 
    96.                   }; 
    97.  
    98.                   return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag); 
    99.               } 
    100.           }); 
    101.       } 
    102.  
    103.       protectedinternalvirtualvoid EndProcessRequest(IAsyncResult asyncResult) { 
    104.           SecurityUtil.ProcessInApplicationTrust(() => { 
    105.               AsyncResultWrapper.End(asyncResult, _processRequestTag); 
    106.           }); 
    107.       } 
    108.  
    109.       privatestaticstring GetMvcVersionString() { 
    110.           // DevDiv 216459: 
    111.           // This code originally used Assembly.GetName(), but that requires FileIOPermission, which isn't granted in 
    112.           // medium trust. However, Assembly.FullName *is* accessible in medium trust. 
    113.           returnnew AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2); 
    114.       } 
    115.  
    116.       protectedvirtualvoid ProcessRequest(HttpContext httpContext) { 
    117.           HttpContextBase iHttpContext = new HttpContextWrapper(httpContext); 
    118.           ProcessRequest(iHttpContext); 
    119.       } 
    120.  
    121.       protectedinternalvirtualvoid ProcessRequest(HttpContextBase httpContext) { 
    122.           SecurityUtil.ProcessInApplicationTrust(() => { 
    123.               IController controller; 
    124.               IControllerFactory factory; 
    125.               ProcessRequestInit(httpContext, out controller, out factory); 
    126.  
    127.               try
    128.                   controller.Execute(RequestContext); 
    129.               } 
    130.               finally
    131.                   factory.ReleaseController(controller); 
    132.               } 
    133.           }); 
    134.       } 
    135.  
    136.       privatevoid ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) { 
    137.           // If request validation has already been enabled, make it lazy. This allows attributes like [HttpPost] (which looks 
    138.           // at Request.Form) to work correctly without triggering full validation. 
    139.           bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(HttpContext.Current); 
    140.           if (isRequestValidationEnabled == true) { 
    141.               ValidationUtility.EnableDynamicValidation(HttpContext.Current); 
    142.           } 
    143.  
    144.           AddVersionHeader(httpContext); 
    145.           RemoveOptionalRoutingParameters(); 
    146.  
    147.           // Get the controller type 
    148.           string controllerName = RequestContext.RouteData.GetRequiredString("controller"); 
    149.  
    150.           // Instantiate the controller and call Execute 
    151.           factory = ControllerBuilder.GetControllerFactory(); 
    152.           controller = factory.CreateController(RequestContext, controllerName); 
    153.           if (controller == null) { 
    154.               thrownew InvalidOperationException( 
    155.                   String.Format( 
    156.                       CultureInfo.CurrentCulture, 
    157.                       MvcResources.ControllerBuilder_FactoryReturnedNull, 
    158.                       factory.GetType(), 
    159.                       controllerName)); 
    160.           } 
    161.       } 
    162.  
    163.       privatevoid RemoveOptionalRoutingParameters() { 
    164.           RouteValueDictionary rvd = RequestContext.RouteData.Values; 
    165.  
    166.           // Get all keys for which the corresponding value is 'Optional'. 
    167.           // ToArray() necessary so that we don't manipulate the dictionary while enumerating. 
    168.           string[] matchingKeys = (from entry in rvd 
    169.                                    where entry.Value == UrlParameter.Optional 
    170.                                    select entry.Key).ToArray(); 
    171.  
    172.           foreach (string key in matchingKeys) { 
    173.               rvd.Remove(key); 
    174.           } 
    175.       } 
    176.       #region IHttpHandler Members 
    177.       bool IHttpHandler.IsReusable { 
    178.           get
    179.               return IsReusable; 
    180.           } 
    181.       } 
    182.  
    183.       void IHttpHandler.ProcessRequest(HttpContext httpContext) { 
    184.           ProcessRequest(httpContext); 
    185.       } 
    186.       #endregion 
    187.       #region IHttpAsyncHandler Members 
    188.       IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { 
    189.           return BeginProcessRequest(context, cb, extraData); 
    190.       } 
    191.  
    192.       void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) { 
    193.           EndProcessRequest(result); 
    194.       } 
    195.       #endregion 
    196.   } 
      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。

  • 相关阅读:
    【先定一个小目标】在Windows下的安装Elasticsearch
    【先定一个小目标】Windows下Redis的安装使用
    【.net core 跨平台】第一步 在Ubuntu16.04 配置.net core环境
    Caf.CMS是一个免费的、 开源,功能齐全的CMS
    使用MicroService4Net 快速创建一个简单的微服务
    记录-div绝对定位针对手机浏览器的区别
    OS X 下不通过Homebrew安装ASP.NET 5开发环境
    结合谷歌地图多边形(polygon)与Sql Server 2008的空间数据类型计算某个点是否在多边形内的注意事项
    插入排序
    修复lvm的逻辑卷
  • 原文地址:https://www.cnblogs.com/fjsnail/p/2870900.html
Copyright © 2011-2022 走看看