zoukankan      html  css  js  c++  java
  • ASP.NET MVC-URL路由

      MVC-即Model,View,Controller,三层架构模式。model作为领域模型,是维持应用状态,提供业务功能的领域模型;View-指UI层,用于和用户的交和页面的展示;而Controller则是定义具体了UI

    逻辑功能。传统的MVC模式,并没有严格的定义,即Model层也可以直接返回给view层数据状态的变化,而非通过Controller来控制的。ASP.NET MVC中,参考了java中的Model2,使得view层和model层是隔离的,不可直接交互的。具体实现方式是,通过定义了一个拦截器-HttpModule,来处理http请求。分析请求中的Controller和Action,Controller被激活后,Action被执行。对于传入Action方法的参数,则是源于请求地址的get或post数据。

      在Controller和Action被执行过程中,它可以调用Model获取或改变其状态。在Action方法执行的最后阶段,选择相应的View,绑定在view上的数据来源与model或基于显示要求进行的简单逻辑计算,我们有时称它为VM-View Model。生成的View最终写入Http回复并返回到浏览器中。

      Model2中完全隔断了View和Model中的联系。Controller作为支配者在model2中尤为明显,用户请求不在由view报告给Controller,而是有拦截器直接转发给Controller。Controller不仅决定着Model的调用,还决定着View的选择和生成。其拦截机制是通过一个自定义的的HttpModule和一个自定义的HttpHandler来实现的。

      一。ASP.NET MVC是如何运行的-URL路由

        ASP.NET定义了一个全局的路由表(RouteTable),路由表中的每个路由对象(RouteData)对应着一个将Comtroller和Action名称作为占位符的URL模板。对于,每个抵达的HTTP请求,ASP.NET MVC会遍历路由表找到一个URL模板的模式与Http请求地址相匹配的路由对象,并最终解析出以Controller和Action名称为核心的路由对象。

        路由对象UML类图:

        

      具体代码如下:

      

     1 namespace WebMvc
     2 {
     3     public class RouteData
     4     {
     5         /// <summary>
     6         /// 包含解析http请求的变量。key可以为controller和action,存储请求中控制器名称和Action名称
     7         /// </summary>
     8         public IDictionary<string,object> Values { get; private set; }
     9 
    10         /// <summary>
    11         /// 表示其他类型变量。属性Namespaces的值从中获取
    12         /// </summary>
    13         public IDictionary<string,object> DataTokens { get; private set; }
    14 
    15         public RouteData() 
    16         {
    17             Values = new Dictionary<string, object>();
    18             DataTokens = new Dictionary<string, object>();
    19             DataTokens.Add("namespance", new List<string>());
    20         }
    21         /// <summary>
    22         /// 获取一个实际处理请求的IHttpHandler对象
    23         /// </summary>
    24         public IRouteHandler RouteHandler { get; set; }
    25 
    26         /// <summary>
    27         /// 返回一个匹配http请求路径的url模式的routeData对象
    28         /// </summary>
    29         public RouteBase Route { get; set; }
    30 
    31         public string Controller 
    32         {
    33             get 
    34             {
    35                 object controllername = string.Empty;
    36                 this.Values.TryGetValue("cotroller", out controllername);
    37                 return (string)controllername;
    38             }
    39         }
    40         public string ActionName 
    41         {
    42             get 
    43             {
    44                 object actionname = string.Empty;
    45                 this.Values.TryGetValue("action", out actionname);
    46                 return (string)actionname;//拆箱
    47             }
    48         }
    49 
    50         public IEnumerable<string> Namespance 
    51         {
    52             get 
    53             {
    54                 return (IEnumerable<string>)this.DataTokens["namespance"];
    55             }
    56         }
    57     }
    58 }
     1 namespace WebMvc
     2 {
     3     /// <summary>
     4     /// 主要具有返回一个具体处理请求的IHttpHandler对象的GetHttpHandler方法
     5     /// </summary>
     6     public interface IRouteHandler
     7     {
     8         IHttpHandler GetHttpHandler(RequestContext requestContext);
     9     }
    10 }
     1 namespace WebMvc
     2 {
     3     /// <summary>
     4     /// Http请求上下文
     5     /// 封装了一个HttpContext对象和RouteData对象
     6     /// </summary>
     7     public class RequestContext
     8     {
     9         public virtual HttpContext HttpContext { get; set; }
    10 
    11         public virtual RouteData RouteData { get; set; }
    12 
    13         public RequestContext(HttpContext httpContext, RouteData routeData) 
    14         {
    15             this.HttpContext = httpContext;
    16             this.RouteData = routeData;
    17         }
    18     }
    19 }

     二。Route和RouteTable

      RouteData具有一个类型为RouteBase的Route属性,表示当前路由表中与当前请求相匹配的路由对象。也就是说,当前的RouteData就是通过这个路由对象对当前Http解析获得的。RouteBase是个抽象类,是所有路由对象的基类。主要包含一个返回当前路由对象的方法GetRouteData..

      

     1 namespace WebMvc
     2 {
     3     /// <summary>
     4     /// 通过对以HttpContextBase对象表示的Http上下文进行解析,从而获取到一个RouteData对象
     5     /// </summary>
     6     public abstract class RouteBase
     7     {
     8         public abstract RouteData GetRouteDara(HttpContextBase httpContextBase);
     9     }
    10 }

      ASP.NET MVC 提供的基于URL模板的路由机制,是通过Route类实现的。Route是RouteBase的子类。UML类图:

      

     1 namespace WebMvc
     2 {
     3     /// <summary>
     4     /// MVC的基于URL模板的路由机制,是通过Route类实现的
     5     /// </summary>
     6     public class Route:RouteBase
     7     {
     8         /// <summary>
     9         /// 处理http请求的对象
    10         /// </summary>
    11         public IRouteHandler RouteHandler { get; set; }
    12 
    13         /// <summary>
    14         /// 代表定义的URL模板
    15         /// </summary>
    16         public string Url { get; set; }
    17 
    18         /// <summary>
    19         /// 其他类型变量
    20         /// </summary>
    21         public IDictionary<string,object> DataToken { get; set; }
    22 
    23         public Route() 
    24         {
    25             this.DataToken = new Dictionary<string, object>();
    26             this.RouteHandler = new MvcRouteHandler();
    27         }
    28 
    29         /// <summary>
    30         /// 比较URL模板与http请求路径是否一致。
    31         /// </summary>
    32         /// <param name="requestUrl">http请求路径</param>
    33         /// <param name="variables">返回一个存储字典,存储http请求路径的actio和controller名称</param>
    34         /// <returns></returns>
    35         protected bool Match(string requestUrl, out IDictionary<string, object> variables) 
    36         {
    37             variables = new Dictionary<string, object>();
    38             var arr_1 = requestUrl.Split('/');
    39             var arr_2 = Url.Split('/');
    40             if (arr_1.Length != arr_2.Length)
    41                 return false;
    42             for (var k = 0; k <= arr_1.Length - 1; k++) 
    43             {
    44                 if (arr_2[k].StartsWith("{") && arr_2[k].EndsWith("}"))
    45                 {
    46                     variables.Add(arr_2[k].Trim("{}".ToCharArray()), arr_1[k]);
    47                 }
    48             }
    49             return true;
    50         }
    51 
    52         /// <summary>
    53         /// 返回一个匹配上的路由对象,如果没有匹配http的请求路径的,则返回一个null.
    54         /// </summary>
    55         /// <param name="httpContextBase"></param>
    56         /// <returns></returns>
    57         public override RouteData GetRouteDara(HttpContextBase httpContextBase)
    58         {
    59             IDictionary<string, object> variables;
    60             if (Match(httpContextBase.Request.AppRelativeCurrentExecutionFilePath.Substring(2), out variables)) 
    61             {
    62                 RouteData routeData = new RouteData();
    63                 foreach (var item in variables) 
    64                 {
    65                     routeData.Values.Add(item.Key, item.Value);
    66                 }
    67                 foreach (var item in DataToken) 
    68                 {
    69                     routeData.DataTokens.Add(item.Key, item.Value);
    70                 }
    71                 routeData.RouteHandler = RouteHandler;
    72 
    73                 return routeData;
    74             }
    75             return null;
    76         }
    77     }
    78 }

    MvcRouteHandler类,实现接口IRouteHandler接口,返回一个HttpHandler对象,具体代码如下:

     1 namespace WebMvc
     2 {
     3     public class MvcRouteHandler:IRouteHandler
     4     {
     5         public IHttpHandler GetHttpHandler(RequestContext requestContext) 
     6         {
     7             return new MvcHandler(requestContext);
     8         }
     9     }
    10 }

     同一个web应用可以采用多种不同的URL模式,故需要注册多个继承RouteBase的对象(Route)来解析HTTp请求。多个路由对象组成一个路由表:RouteTable.

    /// <summary>
        /// RouteTable定义指定路由对象的字典,无参构造初始化
        /// </summary>
        public class RouteTable
        {
            public RouteDictionary Routes { get; private set; }
    
            public RouteTable() 
            {
                Routes = new RouteDictionary();
            }
        }
    
     1  public class RouteDictionary:Dictionary<string,RouteBase>
     2     {
     3         public RouteData GetRouteData(HttpContextBase  httpContextBase) 
     4         {
     5             //this指代字典,Values是字典的value值
     6             foreach (var data in this.Values) 
     7             {
     8                 RouteData routeData = data.GetRouteDara(httpContextBase);
     9                 if (routeData != null)
    10                     return routeData;
    11             }
    12             return null;
    13         }
    14     }
  • 相关阅读:
    [算法] 堆栈
    [刷题] PTA 02-线性结构3 Reversing Linked List
    java IO流 (八) RandomAccessFile的使用
    java IO流 (七) 对象流的使用
    java IO流 (六) 其它的流的使用
    java IO流 (五) 转换流的使用 以及编码集
    java IO流 (四) 缓冲流的使用
    java IO流 (三) 节点流(或文件流)
    java IO流 (二) IO流概述
    java IO流 (一) File类的使用
  • 原文地址:https://www.cnblogs.com/king-tao/p/13350066.html
Copyright © 2011-2022 走看看