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     }

 

posted @ 2020-07-22 23:26  一生安然  阅读(309)  评论(0编辑  收藏  举报