一起谈.NET技术,ASP.NET MVC 路由规则XML化
2011-08-29 19:31
671 查看
最近由于工作关系,重新回顾了ASP.NET MVC 的 1.0 版本。2.0版本还没有研究。
由于MVC框架发展不久,还有很多不足的地方。其中关于路由规则配置这一块问题比较大。首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的。
代码
以下是全部代码
在实现过程中遇到的最大问题就是 参数列表的动态装载 看一下以下代码
这是硬编码实现的路由规则注册
其中 第三个参数(new { controller = "User", action = "Show", id = "0" } ) 是一个匿名对象
该对象如何动态构建成了难题。(才疏学浅)
尝试着传入一个 Dictionary<K,T> 但是没有用,ASP.NET 解析这个参数的时候是以反射形式读取的对象属性。
后来想到了使用代码段 在运行时动态创建对象。
我们将类似代码段
传入方法
即可有运行时动态的创建我们需要的参数对象。
以后就可以方便的在XML注册路由了。
public static void Register(this RouteCollection routes) 对 RouteCollection 对象添加了扩展方法
引入对应的命名空间后就方便的注册了。
改进后的注册方法
由于MVC框架发展不久,还有很多不足的地方。其中关于路由规则配置这一块问题比较大。首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的。
代码
<?xml version="1.0" encoding="utf-8" ?> <MapRoutes> view sourceprint? <!--默认规则--> <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.GetRoot Path())); } /// <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 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); }
即可有运行时动态的创建我们需要的参数对象。
以后就可以方便的在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(); }
相关文章推荐
- 一起谈.NET技术,鲜为人知的ASP.NET MVC 2.0框架高效之谜
- 一起谈.NET技术,浅谈ASP.NET MVC
- 一起谈.NET技术,ASP.NET MVC 3 Beta初体验之超酷的Chart
- 一起谈.NET技术,细数ASP.NET MVC框架的7大顶级功能
- 一起谈.NET技术,Asp.net mvc 2中使用Ajax的三种方式
- 一起谈.NET技术,详解ASP.NET MVC 2中的新ADO.NET实体框架
- 一起谈.NET技术,ASP.NET MVC 3 Beta初体验之WebGrid
- 一起谈.NET技术,Asp.net mvc 3 beta 新特性介绍
- 一起谈.NET技术,ASP.NET MVC之视图引擎
- 一起谈.NET技术,ASP.NET MVC 3 Beta初体验之实用的WebMail
- 一起谈.NET技术,ASP.NET 4的Demo实践:URL路由改进支持
- 一起谈.NET技术,ASP.NET MVC 3 —— Model的使用?
- 一起谈.NET技术,13个不可不知的ASP.NET MVC扩展点
- 一起谈.NET技术,ASP.NET MVC的全球化方案
- 一起谈.NET技术,在Mono 2.8上部署ASP.NET MVC 2
- 一起谈.NET技术,ASP.NET MVC功能详解 变身数据展示达人
- 一起谈.NET技术,ASP.NET MVC & EF 构建智能查询 一、智能查询的需求与设计
- 一起谈.NET技术,关于技术争论(尤其是ASP.NETWebForms 和 ASP.NETMVC 之争)
- 一起谈.NET技术,ASP.NET MVC 3 Beta初体验之超酷的Chart:3D效果
- 一起谈.NET技术,专访微软MVP衣明志:走进ASP.NET MVC 2框架开发