一起谈.NET技术,ASP.NET MVC 路由规则XML化

最近由于工作关系,重新回顾了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>
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();
}

 

时间: 2024-09-20 00:12:37

一起谈.NET技术,ASP.NET MVC 路由规则XML化的相关文章

ASP.NET MVC 路由规则XML化

最近由于工作关系,重新回顾了ASP.NET MVC 的 1.0 版本.2.0版本还没有研究. 由于MVC框架发展不久,还有很多不足的地方.其中关于路由规则配置这一块问题比较大.首先路由规则是在全局配置问价 Global.asax 的 Application_Start()事件中注册的. 代码public static void RegisterRoutes(Route Collection routes) { routes.IgnoreRoute("{resource}.axd/{*pathIn

mvc路由规则,做伪静态

问题描述 mvc路由规则,做伪静态 在路由规则里,写了这样几条规则: //分类路由 routes.MapRoute("category", "list/{filterAttr}-{cateId}-{brandId}-{filterPrice}-{onlyStock}-{sortColumn}-{sortDirection}-{page}.html", new { controller = "catalog", action = "cat

ASP.NET MVC路由扩展:链接和URL的生成

ASP.NET 路由系统通过注册的路由表旨在实现两个"方向"的路有功能,即针对入栈请求的路由和出栈URL的生成.前者通过调用代表全局路由表的RouteCollection对象的GetRouteData方法实现,后者则依赖于RouteCollection的GetVirtualPathData方法,而最终还是落在继承自RouteBase的路由对象的同名方法的调用上.为了编程的方面,ASP.NET MVC为了设计了HtmlHelper和UrlHelper这两个帮助类,我们可以通过调用它们的A

ASP.NET MVC路由扩展:路由映射

上周我写了三篇文章(一.二.三)详细地介绍了ASP.NET的路由系统.ASP.NET的路由系统旨在通过注册URL模板与物理文件之间的映射进而实现请求地址与文件路径之间的分离,但是对于ASP.NET MVC应用来说,请求的目标不再是一个具体的物理文件,而是定义在某个Controller类型中的Action方法.出于自身路由特点的需要,ASP.NET对ASP.NET的路由系统进行了相应的扩展. 一.基本路由映射 通过前面的介绍我们知道基于某个物理文件的路由映射通过调用代表全局路由表的RouteTab

ASP.NET WebAPI 路由规则与POST数据

蛋疼的路由规则约定 在上一篇文章中 我们成功通过AJAX获取到了服务器的数据, 而且服务器根据请求的类型,格式化数据之后再传给客户端. 然而 在上一篇的实例中, 我们为controller程序增加一个GetProducts方法 让这个方法与GetAllProducts方法逻辑一致 public IEnumerable<Product> GetAllProducts() { return products; } public IEnumerable<Product> GetProdu

asp.net mvc 路由问题, 哪位大哥帮看看

问题描述 routes.MapRoute("第一条路由","{controller}/{action}/{identity}",new{controller="Home",action="Index",identity=UrlParameter.Optional});routes.MapRoute("第二条路由",//路由名称"{controller}/{action}/{currentPage}

ASP.NET MVC路由配置问题

问题描述 routes.MapRoute(name:"Category",url:"{action}/{category}/{currentpage}",defaults:new{controller="Home",action="Index",category=UrlParameter.Optional,currentpage="1"});这是我的路由配置一节当路由中的catetgory为ASP.NET这

ASP.Net MVC路由配置的问题

问题描述 最近刚刚接触MVC,有一个动态地址需要解析.格式是:http://www.ABC.com/{QQ}/Home/Index/{id}和http://www.ABC.com/CC/Home/Index/{id}这里的{QQ}是动态的,如果QQ有值的话需要判断是否有效,没有效要跳转到http://www.ABC.com/CC/Home.在网上找了很多资料,但都是处理{Controller}/{Action}的,没看到上一层的解析.请问各位大神这个该如何处理?先谢谢了!还有就是,路由是否同时支

一起谈.NET技术,一个MVC分页Helper

本人写的一个分页Helper,支持普通分页(也就是,首页.上一页.下一页.末页等),综合分页(普通分页和数字分页的综合).下面是分页效果: 分页代码: PagerHelper.cs 代码   1 using System;  2  using System.Collections.Generic;  3 using System.Collections.Specialized;  4 using System.Linq;  5 using System.Web;  6 using System.