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     }
  • 相关阅读:
    VS2005快捷键(转)
    codeSmish使用《转》
    WinForm TextBox数据绑定
    NetTiers抛出"Unable To Load NetTiersServiceSection“的异常
    DELPHi第三方控件使用方法(摘录)
    遠程連接操作
    不同服务器数据库之间的数据操作
    delphi 关闭 MDI 子窗体
    VSS使用手册(转)
    delphi 快捷键
  • 原文地址:https://www.cnblogs.com/king-tao/p/13350066.html
Copyright © 2011-2022 走看看