[转载]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