zoukankan      html  css  js  c++  java
  • 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对象

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

    7、MvcHandler

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

    [csharp] view plaincopy
     
    1. public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState {  
    2.       private static readonly object _processRequestTag = new object();  
    3.       private ControllerBuilder _controllerBuilder;  
    4.   
    5.       internal static readonly string MvcVersion = GetMvcVersionString();  
    6.       public static readonly string MvcVersionHeaderName = "X-AspNetMvc-Version";  
    7.   
    8.       public MvcHandler(RequestContext requestContext) {  
    9.           if (requestContext == null) {  
    10.               throw new 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.       public static bool DisableMvcResponseHeader {  
    29.           get;  
    30.           set;  
    31.       }  
    32.   
    33.       protected virtual bool IsReusable {  
    34.           get {  
    35.               return false;  
    36.           }  
    37.       }  
    38.   
    39.       public RequestContext RequestContext {  
    40.           get;  
    41.           private set;  
    42.       }  
    43.   
    44.       protected internal virtual void AddVersionHeader(HttpContextBase httpContext) {  
    45.           if (!DisableMvcResponseHeader) {  
    46.               httpContext.Response.AppendHeader(MvcVersionHeaderName, MvcVersion);  
    47.           }  
    48.       }  
    49.   
    50.       protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state) {  
    51.           HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);  
    52.           return BeginProcessRequest(iHttpContext, callback, state);  
    53.       }  
    54.   
    55.       protected internal virtual 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.       protected internal virtual void EndProcessRequest(IAsyncResult asyncResult) {  
    104.           SecurityUtil.ProcessInApplicationTrust(() => {  
    105.               AsyncResultWrapper.End(asyncResult, _processRequestTag);  
    106.           });  
    107.       }  
    108.   
    109.       private static string 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.           return new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2);  
    114.       }  
    115.   
    116.       protected virtual void ProcessRequest(HttpContext httpContext) {  
    117.           HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);  
    118.           ProcessRequest(iHttpContext);  
    119.       }  
    120.   
    121.       protected internal virtual void 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.       private void 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.               throw new InvalidOperationException(  
    155.                   String.Format(  
    156.                       CultureInfo.CurrentCulture,  
    157.                       MvcResources.ControllerBuilder_FactoryReturnedNull,  
    158.                       factory.GetType(),  
    159.                       controllerName));  
    160.           }  
    161.       }  
    162.   
    163.       private void 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.  
    177.       #region IHttpHandler Members  
    178.       bool IHttpHandler.IsReusable {  
    179.           get {  
    180.               return IsReusable;  
    181.           }  
    182.       }  
    183.   
    184.       void IHttpHandler.ProcessRequest(HttpContext httpContext) {  
    185.           ProcessRequest(httpContext);  
    186.       }  
    187.       #endregion  
    188.  
    189.       #region IHttpAsyncHandler Members  
    190.       IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {  
    191.           return BeginProcessRequest(context, cb, extraData);  
    192.       }  
    193.   
    194.       void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) {  
    195.           EndProcessRequest(result);  
    196.       }  
    197.       #endregion  
    198.   }  


    值得一提的是,在MVC3中已经实现异步处理(IHttpAsyncHandler)

    8、StopRoutingHandler类

        表示一个“不处理URL的路由处理类”,  比如MVC在RouteCollection类型上扩展了一个IgnoreRoute方法,用于指示路由系统忽略处理指定的url。其实现方式是生成一个Route对象,指定其RouteHandler属性为一个StopRoutingHandler对象。

    9、IRouteConstraint接口

        用于构建Route.Constraints属性,表示一个约束条件。Match方法用于检查url是否符合路由规则,符合返回true,否则false。

  • 相关阅读:
    Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) Finished D. Arpa and a list of numbers
    Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) C. Five Dimensional Points
    Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) B. Arpa and an exam about geometry
    Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) A. Arpa and a research in Mexican wave
    hdu 5510
    长沙理工大学第十二届ACM大赛
    Codeforces Round #336 (Div. 2) D. Zuma
    百(垃)度(圾)之星初赛B hdu6114
    百(垃)度(圾)之星初赛B hdu6119
    Codeforces Round #428C
  • 原文地址:https://www.cnblogs.com/cxzdy/p/3898350.html
Copyright © 2011-2022 走看看