ASP.NET MVC 路由規則XML化

來源:互聯網
上載者:User

  很久沒寫文章了,不是懶得寫,是寫不出。。

  最近由於工作關係,重新回顧了ASP.NET MVC 的 1.0 版本。2.0版本還沒有研究。

由於MVC架構發展不久,還有很多不足的地方。其中關於路由規則配置這一塊問題比較大。首先路由規則是在全域配置問價 Global.asax 的 Application_Start()事件中註冊的。

 

public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            routes.MapRoute(                "User",                                              // Route name                "{controller}/{action}/{id}",                           // URL with parameters                new { controller = "User", action = "Show", id = "0" }  // Parameter defaults            );        }        protected void Application_Start()        {            RegisterRoutes(RouteTable.Routes);        }

 

預設硬式編碼方式使得以後可維護程度大大降低。MVC 1.0 似乎沒有提供很好的基於設定檔的路由規則設定。所以只好自己實現了。直到寫這篇文章時,才找到了一個比較好的解決方案。

 

以下是 自訂的XML 格式

<?xml version="1.0" encoding="utf-8" ?><MapRoutes>
  <!--預設規則-->  <MapRoute name="Default" url="{controller}/{action}">    <Params>      <Item key="controller" default="Article"/>      <Item key="action" default="Index"/>    </Params>  </MapRoute>  <!--顯示新聞列表的路由規則-->  <MapRoute name="ShowArticleList" url="{controller}/{action}/{typeId}/{pageIndex}/{pageSize}">    <Params>      <Item key="controller" default="Article"/>      <Item key="action" default="Index"/>      <Item key="typeId" default="1"/>      <Item key="pageIndex" default="1"/>      <Item key="pageSize" default="10"/>    </Params>  </MapRoute></MapRoutes>

 

一下是全部代碼

/* *********************************************** * 作者 :湯曉華/tension 任何轉載請務必保留此頭部資訊 著作權 盜版必究 * Email:tension1990@hotmail.com  * 描述 : * 建立時間:2010-3-9 15:17:26 * 修改曆史: * ***********************************************/using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Web.Routing;using System.Web.Mvc;using System.Xml.Linq;using Microsoft.CSharp;using System.CodeDom.Compiler;namespace Tension.Mvc{    public static class RouteHelper    {        /// <summary>        /// 從XML檔案中註冊路由規則        /// </summary>        /// <param name="routes"></param>        /// <param name="cfgFile"></param>        public static void Register(this RouteCollection routes, string cfgFile)        {            IList<Route> Routes = GetRoutes(cfgFile);            foreach (var item in Routes)            {                //路由規則對象                object obj = CreateObjectFormString(item.ToString(), item.Name);                routes.MapRoute(                       item.Name,               // Route name                       item.Url,                // URL with parameters                        obj                     // Parameter defaults                   );            }        }        /// <summary>        ///  從XML檔案中註冊路由規則 預設檔案為網站根目錄下MapRoute.config        /// </summary>        /// <param name="routes"></param>        public static void Register(this RouteCollection routes)        {            Register(routes, string.Format("{0}\\MapRoute.config", Tension.ServerInfo.GetRootPath()));        }        /// <summary>        /// 從string動態建立類對象        /// </summary>        /// <param name="codeString"></param>        /// <param name="className"></param>        /// <returns></returns>        private static object CreateObjectFormString(string codeString, string className)        {            CSharpCodeProvider ccp = new CSharpCodeProvider();            CompilerParameters param = new CompilerParameters(new string[] { "System.dll" });            CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString);            Type type = cr.CompiledAssembly.GetType(className);            return type.GetConstructor(System.Type.EmptyTypes).Invoke(null);        }        /// <summary>        /// 從XML檔案中解析路由規則        /// </summary>        /// <param name="configFile"></param>        /// <returns></returns>        private static IList<Route> GetRoutes(string configFile)        {            StringBuilder sb = new StringBuilder();            Console.WriteLine(sb.ToString());            IList<Route> Routes = new List<Route>();            XElement xe = XElement.Load(configFile);            #region MyRegion            foreach (var item in xe.Elements("MapRoute"))            {                //名稱屬性                XAttribute xaName = item.Attribute("name");                if (xaName == null || string.IsNullOrEmpty(xaName.Value))                {                    throw new ArgumentNullException("name!說明:路由設定檔中某規則缺少name屬性或name屬性的值為空白字串");                }                //URL屬性                XAttribute urlName = item.Attribute("url");                if (urlName == null || string.IsNullOrEmpty(urlName.Value))                {                    throw new ArgumentNullException("url!說明:路由設定檔中某規則缺少url屬性或url屬性的值為空白字串");                }                Dictionary<string, string> DictParams = new Dictionary<string, string>();                #region MyRegion                foreach (var pItem in item.Element("Params").Elements("Item"))                {                    XAttribute itemKey = pItem.Attribute("key");                    if (itemKey == null || string.IsNullOrEmpty(itemKey.Value))                    {                        throw new ArgumentNullException("Item->key!說明:路由設定檔中某規則缺少Item->key屬性或Item->key屬性的值為空白字串");                    }                    XAttribute itemDefault = pItem.Attribute("default");                    if (itemDefault == null || string.IsNullOrEmpty(itemDefault.Value))                    {                        throw new ArgumentNullException("Item->default!說明:路由設定檔中某規則缺少Item->default屬性或Item->default屬性的值為空白字串");                    }                    DictParams.Add(itemKey.Value, itemDefault.Value);                }                #endregion                Routes.Add(new Route() { Name = xaName.Value, Url = urlName.Value, Params = DictParams });            }            #endregion            return Routes;        }    }    /// <summary>    /// 路由規則    /// </summary>    public class Route    {        public string Name { get; set; }        public string Url { get; set; }        public Dictionary<string, string> Params { get; set; }        /// <summary>        /// 重寫ToString 方法 產生需要動態程式碼片段        /// </summary>         /// <returns></returns>        public override string ToString()        {            StringBuilder sb = new StringBuilder();            sb.AppendFormat("public class {0}", Name);            sb.Append("{");            foreach (var item in Params)            {                sb.AppendFormat("public string {0}", item.Key);                sb.Append("{get{return \"");                sb.Append(item.Value);                sb.Append("\";}} ");            }            sb.Append("}");            return sb.ToString();        }    }}

 

在實現過程中遇到的最大問題就是 參數列表的動態裝載 看一下以下代碼

 routes.MapRoute(                "User",                                              // Route name                "{controller}/{action}/{id}",                           // URL with parameters                new { controller = "User", action = "Show", id = "0" }  // Parameter defaults            );

 

這是寫入程式碼實現的路由規則註冊

其中 第三個參數(new { controller = "User", action = "Show", id = "0" } ) 是一個匿名對象

該對象如何動態構建成了難題。(才疏學淺)

嘗試著傳入一個 Dictionary<K,T> 但是沒有用,ASP.NET 解析這個參數的時候是以反射形式讀取的對象屬性。

後來想到了使用程式碼片段 在運行時動態建立對象。

 

我們將類似程式碼片段

public class Default{public string controller{get{return "Article";}} public string action{get{return "Index";}} public string id{get{return "0";}} public string page{get{return "1";}} public string size{get{return "10";}} }

 

傳入方法

 

private static object CreateObjectFormString(string codeString, string className)        {            CSharpCodeProvider ccp = new CSharpCodeProvider();            CompilerParameters param = new CompilerParameters(new string[] { "System.dll" });            CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString);            Type type = cr.CompiledAssembly.GetType(className);            return type.GetConstructor(System.Type.EmptyTypes).Invoke(null);        }

 

即可有運行時動態建立我們需要的參數對象。

以後就可以方便的在XML註冊路由了。

public static void Register(this RouteCollection routes)  對 RouteCollection 對象添加了擴充方法

引入對應的命名空間後就方便的註冊了。

 

改進後的註冊方法

 

public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");        }        protected void Application_Start()        {            RegisterRoutes(RouteTable.Routes);            //執行RouteCollection的擴充方法 用來註冊XML檔案中的路由配置資訊            RouteTable.Routes.Register();        }

 

代碼

/tandly/MvcRouteHelper.rar

 

蘇州 晴

湯曉華 QQ 1881597 MSN tension1990@hotmail.com

2010 03 10

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.