zoukankan      html  css  js  c++  java
  • 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>
      <!--默认规则-->
      <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.GetRootPath()));
            }
    
    
            /// <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();
            }

    代码下载地址

    /tandly/MvcRouteHelper.rar

    苏州 晴

    汤晓华 QQ 1881597 MSN tension1990@hotmail.com

    2010 03 10

  • 相关阅读:
    HDU 5642 King's Order 动态规划
    HDU 5640 King's Cake GCD
    HDU 5641 King's Phone 模拟
    HDU 5299 Circles Game 博弈论 暴力
    HDU 5294 Tricks Device 网络流 最短路
    HDU 5289 Assignment rmq
    HDU 5288 OO’s Sequence 水题
    星际争霸 虚空之遗 人族5BB 操作流程
    Codeforces Beta Round #3 D. Least Cost Bracket Sequence 优先队列
    Codeforces Beta Round #3 C. Tic-tac-toe 模拟题
  • 原文地址:https://www.cnblogs.com/tandly/p/1682301.html
Copyright © 2011-2022 走看看