[转载]ASP.NET MVC 路由规则XML化 – 汤家大院 – 博客园.
很久没写文章了,不是懒得写,是写不出。。
最近由于工作关系,重新回顾了ASP.NET MVC 的 1.0 版本。2.0版本还没有研究。
由于MVC框架发展不久,还有很多不足的地方。其中关于路由规则配置这一块问题比较大。首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的。
01 |
public static void RegisterRoutes(RouteCollection routes) |
03 |
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); |
07 |
"{controller}/{action}/{id}", |
08 |
new { controller = "User", action = "Show", id = "0" } |
12 |
protected void Application_Start() |
15 |
RegisterRoutes(RouteTable.Routes); |
默认硬编码的方式使得以后可维护程度大大降低。MVC 1.0 似乎没有提供很好的基于配置文件的路由规则设置。所以只好自己实现了。直到写这篇文章时,才找到了一个比较好的解决方案。
以下是 自定义的XML 格式
1 |
<?xml version="1.0" encoding="utf-8" ?> |
02 |
<MapRoute name="Default" url="{controller}/{action}"> |
04 |
<Item key="controller" default="Article"/> |
05 |
<Item key="action" default="Index"/> |
10 |
<MapRoute name="ShowArticleList" url="{controller}/{action}/{typeId}/{pageIndex}/{pageSize}"> |
12 |
<Item key="controller" default="Article"/> |
13 |
<Item key="action" default="Index"/> |
14 |
<Item key="typeId" default="1"/> |
15 |
<Item key="pageIndex" default="1"/> |
16 |
<Item key="pageSize" default="10"/> |
一下是全部代码
009 |
using System.Collections.Generic; |
012 |
using System.Web.Routing; |
013 |
using System.Web.Mvc; |
014 |
using System.Xml.Linq; |
015 |
using Microsoft.CSharp; |
016 |
using System.CodeDom.Compiler; |
018 |
namespace Tension.Mvc |
020 |
public static class RouteHelper |
025 |
/// <param name="routes"></param> |
026 |
/// <param name="cfgFile"></param> |
027 |
public static void Register(this RouteCollection routes, string cfgFile) |
030 |
IList<Route> Routes = GetRoutes(cfgFile); |
032 |
foreach (var item in Routes) |
035 |
object obj = CreateObjectFormString(item.ToString(), item.Name); |
046 |
/// 从XML文件中注册路由规则 默认文件为网站根目录下MapRoute.config |
048 |
/// <param name="routes"></param> |
049 |
public static void Register(this RouteCollection routes) |
051 |
Register(routes, string.Format("{0}\\MapRoute.config", Tension.ServerInfo.GetRootPath())); |
058 |
/// <param name="codeString"></param> |
059 |
/// <param name="className"></param> |
060 |
/// <returns></returns> |
061 |
private static object CreateObjectFormString(string codeString, string className) |
063 |
CSharpCodeProvider ccp = new CSharpCodeProvider(); |
064 |
CompilerParameters param = new CompilerParameters(new string[] { "System.dll" }); |
065 |
CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString); |
066 |
Type type = cr.CompiledAssembly.GetType(className); |
067 |
return type.GetConstructor(System.Type.EmptyTypes).Invoke(null); |
073 |
/// <param name="configFile"></param> |
074 |
/// <returns></returns> |
075 |
private static IList<Route> GetRoutes(string configFile) |
077 |
StringBuilder sb = new StringBuilder(); |
080 |
Console.WriteLine(sb.ToString()); |
081 |
IList<Route> Routes = new List<Route>(); |
083 |
XElement xe = XElement.Load(configFile); |
086 |
foreach (var item in xe.Elements("MapRoute")) |
090 |
XAttribute xaName = item.Attribute("name"); |
091 |
if (xaName == null || string.IsNullOrEmpty(xaName.Value)) |
093 |
throw new ArgumentNullException("name!说明:路由配置文件中某规则缺少name属性或name属性的值为空字符串"); |
097 |
XAttribute urlName = item.Attribute("url"); |
098 |
if (urlName == null || string.IsNullOrEmpty(urlName.Value)) |
100 |
throw new ArgumentNullException("url!说明:路由配置文件中某规则缺少url属性或url属性的值为空字符串"); |
104 |
Dictionary<string, string> DictParams = new Dictionary<string, string>(); |
109 |
foreach (var pItem in item.Element("Params").Elements("Item")) |
111 |
XAttribute itemKey = pItem.Attribute("key"); |
112 |
if (itemKey == null || string.IsNullOrEmpty(itemKey.Value)) |
114 |
throw new ArgumentNullException("Item->key!说明:路由配置文件中某规则缺少Item->key属性或 Item->key属性的值为空字符串"); |
117 |
XAttribute itemDefault = pItem.Attribute("default"); |
118 |
if (itemDefault == null || string.IsNullOrEmpty(itemDefault.Value)) |
120 |
throw new ArgumentNullException("Item->default!说明:路由配置文件中某规则缺少Item->default属 性或Item->default属性的值为空字符串"); |
122 |
DictParams.Add(itemKey.Value, itemDefault.Value); |
126 |
Routes.Add(new Route() { Name = xaName.Value, Url = urlName.Value, Params = DictParams }); |
142 |
public string Name { get; set; } |
143 |
public string Url { get; set; } |
144 |
public Dictionary<string, string> Params { get; set; } |
147 |
/// 重写ToString 方法 产生需要动态代码段 |
149 |
/// <returns></returns> |
150 |
public override string ToString() |
152 |
StringBuilder sb = new StringBuilder(); |
153 |
sb.AppendFormat("public class {0}", Name); |
155 |
foreach (var item in Params) |
157 |
sb.AppendFormat("public string {0}", item.Key); |
158 |
sb.Append("{get{return \""); |
159 |
sb.Append(item.Value); |
164 |
return sb.ToString(); |
在实现过程中遇到的最大问题就是 参数列表的动态装载 看一下以下代码
3 |
"{controller}/{action}/{id}", |
4 |
new { controller = "User", action = "Show", id = "0" } |
这是硬编码实现的路由规则注册
其中 第三个参数(new { controller = “User”, action = “Show”, id = “0” } ) 是一个匿名对象
该对象如何动态构建成了难题。(才疏学浅)
尝试着传入一个 Dictionary<K,T> 但是没有用,ASP.NET 解析这个参数的时候是以反射形式读取的对象属性。
后来想到了使用代码段 在运行时动态创建对象。
我们将类似代码段
1 |
public class Default{public string controller{get{return "Article";}} public str |
2 |
ing action{get{return "Index";}} public string id{get{return "0";}} public strin |
3 |
g page{get{return "1";}} public string size{get{return "10";}} } |
传入方法
1 |
private static object CreateObjectFormString(string codeString, string className) |
3 |
CSharpCodeProvider ccp = new CSharpCodeProvider(); |
4 |
CompilerParameters param = new CompilerParameters(new string[] { "System.dll" }); |
5 |
CompilerResults cr = ccp.CompileAssemblyFromSource(param, codeString); |
6 |
Type type = cr.CompiledAssembly.GetType(className); |
7 |
return type.GetConstructor(System.Type.EmptyTypes).Invoke(null); |
即可有运行时动态的创建我们需要的参数对象。
以后就可以方便的在XML注册路由了。
public static void Register(this RouteCollection routes) 对 RouteCollection 对象添加了扩展方法
引入对应的命名空间后就方便的注册了。
改进后的注册方法
01 |
public static void RegisterRoutes(RouteCollection routes) |
03 |
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); |
07 |
protected void Application_Start() |
10 |
RegisterRoutes(RouteTable.Routes); |
13 |
RouteTable.Routes.Register(); |
代码下载地址
/tandly/MvcRouteHelper.rar
苏州 晴
汤晓华 QQ 1881597 MSN tension1990@hotmail.com
2010 03 10