赞助商
由于MVC框架发展不久,还有很多不足的地方。其中关于路由规则配置这一块问题比较大。首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的。(文/tandly
  1. 01        public static void RegisterRoutes(RouteCollection routes)
  2. 02            {
  3. 03                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4. 04       
  5. 05                routes.MapRoute(
  6. 06                    "User",                                              // Route name
  7. 07                    "{controller}/{action}/{id}",                          // URL with parameters
  8. 08                    new { controller = "User", action = "Show", id = "0" }  // Parameter defaults
  9. 09                );
  10. 10            }
  11. 11       
  12. 12            protected void Application_Start()
  13. 13            {
  14. 14       
  15. 15                RegisterRoutes(RouteTable.Routes);
  16. 16       
  17. 17            }
复制代码
默认硬编码的方式使得以后可维护程度大大降低。MVC 1.0 似乎没有提供很好的基于配置文件的路由规则设置。所以只好自己实现了。直到写这篇文章时,才找到了一个比较好的解决方案。

以下是 自定义的XML 格式
  1. 1        <?xml version="1.0" encoding="utf-8" ?>
  2. 2        <MapRoutes>
  3. view source
  4. print?
  5. 01          <!--默认规则-->
  6. 02          <MapRoute name="Default" url="{controller}/{action}">
  7. 03            <Params>
  8. 04              <Item key="controller" default="Article"/>
  9. 05              <Item key="action" default="Index"/>
  10. 06            </Params>
  11. 07          </MapRoute>
  12. 08       
  13. 09          <!--显示新闻列表的路由规则 -->
  14. 10          <MapRoute name="ShowArticleList" url="{controller}/{action}/{typeId}/{pageIndex}/{pageSize}">
  15. 11            <Params>
  16. 12              <Item key="controller" default="Article"/>
  17. 13              <Item key="action" default="Index"/>
  18. 14              <Item key="typeId" default="1"/>
  19. 15              <Item key="pageIndex" default="1"/>
  20. 16              <Item key="pageSize" default="10"/>
  21. 17            </Params>
  22. 18          </MapRoute>
  23. 19       
  24. 20        </MapRoutes>
复制代码
以下是全部代码
  1. 001        /* ***********************************************
  2. 002        * 作者 :汤晓华/tension 任何转载请务必保留此头部信息 版权所有 盗版必究
  3. 003        * Email:tension1990@hotmail.com
  4. 004        * 描述 :
  5. 005        * 创建时间:2010-3-9 15:17:26
  6. 006        * 修改历史:
  7. 007        * ***********************************************/
  8. 008        using System;
  9. 009        using System.Collections.Generic;
  10. 010        using System.Linq;
  11. 011        using System.Text;
  12. 012        using System.Web.Routing;
  13. 013        using System.Web.Mvc;
  14. 014        using System.Xml.Linq;
  15. 015        using Microsoft.CSharp;
  16. 016        using System.CodeDom.Compiler;
  17. 017       
  18. 018        namespace Tension.Mvc
  19. 019        {
  20. 020            public static class RouteHelper
  21. 021            {
  22. 022                /// <summary>
  23. 023                /// 从XML文件中注册路由规则
  24. 024                /// </summary>
  25. 025                /// <param name="routes"></param>
  26. 026                /// <param name="cfgFile"></param>
  27. 027                public static void Register(this RouteCollection routes, string cfgFile)
  28. 028                {
  29. 029       
  30. 030                    IList<Route> Routes = GetRoutes(cfgFile);
  31. 031       
  32. 032                    foreach (var item in Routes)
  33. 033                    {
  34. 034                        //路由规则对象
  35. 035                        object obj = CreateObjectFormString(item.ToString(), item.Name);
  36. 036                        routes.MapRoute(
  37. 037                              item.Name,              // Route name
  38. 038                              item.Url,                // URL with parameters
  39. 039                                obj                    // Parameter defaults
  40. 040                          );
  41. 041       
  42. 042                    }
  43. 043                }
  44. 044       
  45. 045                /// <summary>
  46. 046                ///  从XML文件中注册路由规则 默认文件为网站根目录下MapRoute.config
  47. 047                /// </summary>
  48. 048                /// <param name="routes"></param>
  49. 049                public static void Register(this RouteCollection routes)
  50. 050                {
  51. 051                    Register(routes, string.Format("{0}\\MapRoute.config", Tension.ServerInfo.GetRootPath()));
  52. 052                }
  53. 053       
  54. 054       
  55. 055                /// <summary>
  56. 056                /// 从string动态创建类对象
  57. 057                /// </summary>
  58. 058                /// <param name="codeString"></param>
  59. 059                /// <param name="className"></param>
  60. 060                /// <returns></returns>
  61. 061                private static object CreateObjectFormString(string codeString, string className)
  62. 062                {
  63. 063                    CSharpCodeProvider ccp = new CSharpCodeProvider();
  64. 064                    CompilerParameters param = new CompilerParameters(new string[] { "System.dll" });
  65. 065                    CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString);
  66. 066                    Type type = cr.CompiledAssembly.GetType(className);
  67. 067                    return type.GetConstructor(System.Type.EmptyTypes).Invoke(null);
  68. 068                }
  69. 069       
  70. 070                /// <summary>
  71. 071                /// 从XML文件中解析路由规则
  72. 072                /// </summary>
  73. 073                /// <param name="configFile"></param>
  74. 074                /// <returns></returns>
  75. 075                private static IList<Route> GetRoutes(string configFile)
  76. 076                {
  77. 077                    StringBuilder sb = new StringBuilder();
  78. 078       
  79. 079       
  80. 080                    Console.WriteLine(sb.ToString());
  81. 081                    IList<Route> Routes = new List<Route>();
  82. 082       
  83. 083                    XElement xe = XElement.Load(configFile);
  84. 084       
  85. 085                    #region MyRegion
  86. 086                    foreach (var item in xe.Elements("MapRoute"))
  87. 087                    {
  88. 088       
  89. 089                        //名称属性
  90. 090                        XAttribute xaName = item.Attribute("name");
  91. 091                        if (xaName == null || string.IsNullOrEmpty(xaName.Value))
  92. 092                        {
  93. 093                            throw new ArgumentNullException("name!说明:路由配置文件中某规则缺少name属性或name属性的值为空字符串");
  94. 094                        }
  95. 095       
  96. 096                        //URL 属性
  97. 097                        XAttribute urlName = item.Attribute("url");
  98. 098                        if (urlName == null || string.IsNullOrEmpty(urlName.Value))
  99. 099                        {
  100. 100                            throw new ArgumentNullException("url!说明:路由配置文件中某规则缺少url属性或url属性的值为空字符串");
  101. 101                        }
  102. 102       
  103. 103       
  104. 104                        Dictionary<string, string> DictParams = new Dictionary<string, string>();
  105. 105       
  106. 106       
  107. 107       
  108. 108                        #region MyRegion
  109. 109                        foreach (var pItem in item.Element("Params").Elements("Item"))
  110. 110                        {
  111. 111                            XAttribute itemKey = pItem.Attribute("key");
  112. 112                            if (itemKey == null || string.IsNullOrEmpty(itemKey.Value))
  113. 113                            {
  114. 114                                throw new ArgumentNullException("Item->key!说明:路由配置文件中某规则缺少Item->key属性或 Item->key属性的值为空字符串");
  115. 115                            }
  116. 116       
  117. 117                            XAttribute itemDefault = pItem.Attribute("default");
  118. 118                            if (itemDefault == null || string.IsNullOrEmpty(itemDefault.Value))
  119. 119                            {
  120. 120                                throw new ArgumentNullException("Item->default!说明:路由配置文件中某规则缺少Item->default属性或Item->default属性的值为空字符串");
  121. 121                            }
  122. 122                            DictParams.Add(itemKey.Value, itemDefault.Value);
  123. 123                        }
  124. 124                        #endregion
  125. 125       
  126. 126                        Routes.Add(new Route() { Name = xaName.Value, Url = urlName.Value, Params = DictParams });
  127. 127       
  128. 128       
  129. 129                    }
  130. 130                    #endregion
  131. 131       
  132. 132                    return Routes;
  133. 133                }
  134. 134            }
  135. 135       
  136. 136       
  137. 137            /// <summary>
  138. 138            /// 路由规则
  139. 139            /// </summary>
  140. 140            public class Route
  141. 141            {
  142. 142                public string Name { get; set; }
  143. 143                public string Url { get; set; }
  144. 144                public Dictionary<string, string> Params { get; set; }
  145. 145       
  146. 146                /// <summary>
  147. 147                /// 重写ToString 方法 产生需要动态代码段
  148. 148                /// </summary>
  149. 149                /// <returns></returns>
  150. 150                public override string ToString()
  151. 151                {
  152. 152                    StringBuilder sb = new StringBuilder();
  153. 153                    sb.AppendFormat("public class {0}", Name);
  154. 154                    sb.Append("{");
  155. 155                    foreach (var item in Params)
  156. 156                    {
  157. 157                        sb.AppendFormat("public string {0}", item.Key);
  158. 158                        sb.Append("{get{return \"");
  159. 159                        sb.Append(item.Value);
  160. 160                        sb.Append("\";}} ");
  161. 161                    }
  162. 162       
  163. 163                    sb.Append("}");
  164. 164                    return sb.ToString();
  165. 165                }
  166. 166            }
  167. 167        }
复制代码
在实现过程中遇到的最大问题就是 参数列表的动态装载 看一下以下代码
  1. 1        routes.MapRoute(
  2. 2                      "User",                                              // Route name
  3. 3                      "{controller}/{action}/{id}",                          // URL with parameters
  4. 4                      new { controller = "User", action = "Show", id = "0" }  // Parameter defaults
  5. 5                  );
复制代码
这是硬编码实现的路由规则注册

其中 第三个参数(new { controller = "User", action = "Show", id = "0" } ) 是一个匿名对象

该对象如何动态构建成了难题。(才疏学浅)

尝试着传入一个 Dictionary<K,T> 但是没有用,ASP.NET 解析这个参数的时候是以反射形式读取的对象属性。

后来想到了使用代码段 在运行时动态创建对象。

我们将类似代码段
  1. 1        public class Default{public string controller{get{return "Article";}} public str
  2. 2        ing action{get{return "Index";}} public string id{get{return "0";}} public strin
  3. 3        g page{get{return "1";}} public string size{get{return "10";}} }
复制代码
传入方法
  1. 1        private static object CreateObjectFormString(string codeString, string className)
  2. 2                {
  3. 3                    CSharpCodeProvider ccp = new CSharpCodeProvider();
  4. 4                    CompilerParameters param = new CompilerParameters(new string[] { "System.dll" });
  5. 5                    CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString);
  6. 6                    Type type = cr.CompiledAssembly.GetType(className);
  7. 7                    return type.GetConstructor(System.Type.EmptyTypes).Invoke(null);
  8. 8                }
复制代码
即可有运行时动态的创建我们需要的参数对象。

以后就可以方便的在XML注册路由了。

public static void Register(this RouteCollection routes)  对 RouteCollection 对象添加了扩展方法

引入对应的命名空间后就方便的注册了。

改进后的注册方法
  1. 01        public static void RegisterRoutes(RouteCollection routes)
  2. 02                {
  3. 03                    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4. 04       
  5. 05                }
  6. 06       
  7. 07                protected void Application_Start()
  8. 08                {
  9. 09       
  10. 10                    RegisterRoutes(RouteTable.Routes);
  11. 11       
  12. 12                    //执行 RouteCollection的扩展方法 用来注册XML文件中的路由配置信息
  13. 13                    RouteTable.Routes.Register();
  14. 14                }
复制代码
代码下载地址:
赞助商
赞助商
TOP