淺析ASP.NET MVC路由規(guī)則XML化的方法
本文主要針對(duì)的是ASP.NET MVC路由規(guī)則的問(wèn)題,作者本次所研究的是ASP.NET MVC路由規(guī)則XML,希望那個(gè)通過(guò)本文能對(duì)大家有所幫助。
最近由于工作關(guān)系,重新回顧了ASP.NET MVC的1.0 版本。2.0版本還沒(méi)有研究。
由于MVC框架發(fā)展不久,還有很多不足的地方。其中關(guān)于路由規(guī)則配置這一塊問(wèn)題比較大。首先路由規(guī)則是在全局配置問(wèn)價(jià) Global.asax 的 Application_Start()事件中注冊(cè)的。
- 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);
- }
默認(rèn)硬編碼的方式使得以后可維護(hù)程度大大降低。MVC 1.0 似乎沒(méi)有提供很好的基于配置文件的路由規(guī)則設(shè)置。所以只好自己實(shí)現(xiàn)了。直到寫(xiě)這篇文章時(shí),才找到了一個(gè)比較好的解決方案。
以下是 自定義的XML 格式
- <?xml version="1.0" encoding="utf-8" ?>
- <MapRoutes>
- <!--默認(rèn)規(guī)則-->
- <MapRoute name="Default" url="{controller}/{action}">
- <Params>
- <Item key="controller" default="Article"/>
- <Item key="action" default="Index"/>
- </Params>
- </MapRoute>
- <!--顯示新聞列表的路由規(guī)則-->
- <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 任何轉(zhuǎn)載請(qǐng)務(wù)必保留此頭部信息 版權(quán)所有 盜版必究
- * Email:tension1990@hotmail.com
- * 描述 :
- * 創(chuàng)建時(shí)間: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文件中注冊(cè)路由規(guī)則
- /// </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)
- {
- //路由規(guī)則對(duì)象
- object obj = CreateObjectFormString(item.ToString(), item.Name);
- routes.MapRoute(
- item.Name, // Route name
- item.Url, // URL with parameters
- obj // Parameter defaults
- );
- }
- }
- /// <summary>
- /// 從XML文件中注冊(cè)路由規(guī)則 默認(rèn)文件為網(wǎng)站根目錄下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動(dòng)態(tài)創(chuàng)建類對(duì)象
- /// </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文件中解析路由規(guī)則
- /// </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!說(shuō)明:路由配置文件中某規(guī)則缺少name屬性或name屬性的值為空字符串");
- }
- //URL屬性
- XAttribute urlName = item.Attribute("url");
- if (urlName == null || string.IsNullOrEmpty(urlName.Value))
- {
- throw new ArgumentNullException("url!說(shuō)明:路由配置文件中某規(guī)則缺少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!說(shuō)明:路由配置文件中某規(guī)則缺少Item->key屬性或Item->key屬性的值為空字符串");
- }
- XAttribute itemDefault = pItem.Attribute("default");
- if (itemDefault == null || string.IsNullOrEmpty(itemDefault.Value))
- {
- throw new ArgumentNullException("Item->default!說(shuō)明:路由配置文件中某規(guī)則缺少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>
- /// 路由規(guī)則
- /// </summary>
- public class Route
- {
- public string Name { get; set; }
- public string Url { get; set; }
- public Dictionary<string, string> Params { get; set; }
- /// <summary>
- /// 重寫(xiě)ToString 方法 產(chǎn)生需要?jiǎng)討B(tài)代碼段
- /// </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();
- }
- }
- }
在實(shí)現(xiàn)過(guò)程中遇到的最大問(wèn)題就是 參數(shù)列表的動(dòng)態(tài)裝載 看一下以下代碼
- routes.MapRoute(
- "User", // Route name
- "{controller}/{action}/{id}", // URL with parameters
- new { controller = "User", action = "Show", id = "0" } // Parameter defaults
- );
這是硬編碼實(shí)現(xiàn)的路由規(guī)則注冊(cè)
其中 第三個(gè)參數(shù)(new { controller = "User", action = "Show", id = "0" } ) 是一個(gè)匿名對(duì)象
該對(duì)象如何動(dòng)態(tài)構(gòu)建成了難題。(才疏學(xué)淺)
嘗試著傳入一個(gè) Dictionary<K,T> 但是沒(méi)有用,ASP.NET 解析這個(gè)參數(shù)的時(shí)候是以反射形式讀取的對(duì)象屬性。
后來(lái)想到了使用代碼段 在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建對(duì)象。
我們將類似代碼段
- public class Default{public string controller{get{return "Article";}} public str
- ing action{get{return "Index";}} public string id{get{return "0";}} public strin
- g 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);
- }
即可有運(yùn)行時(shí)動(dòng)態(tài)的創(chuàng)建我們需要的參數(shù)對(duì)象。
以后就可以方便的在XML注冊(cè)路由了。
public static void Register(this RouteCollection routes) 對(duì) RouteCollection 對(duì)象添加了擴(kuò)展方法
引入對(duì)應(yīng)的命名空間后就方便的注冊(cè)了。
改進(jìn)后的注冊(cè)方法
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- }
- protected void Application_Start()
- {
- RegisterRoutes(RouteTable.Routes);
- //執(zhí)行RouteCollection的擴(kuò)展方法 用來(lái)注冊(cè)XML文件中的路由配置信息
- RouteTable.Routes.Register();
- }
代碼下載地址
/tandly/MvcRouteHelper.rar
原文標(biāo)題:ASP.NET MVC路由規(guī)則XML化
鏈接:http://www.cnblogs.com/tandly/archive/2010/03/10/1682301.html
【編輯推薦】