• 一起谈.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();
    }

  • 相关阅读:
    Eclipse中创建新的Spring Boot项目
    解决win下无法ping通VM虚拟机CentOS系统的方法
    32位centos下安装jdk1.7报Permission denied处理方式
    Windows下安装HBase
    15个nosql数据库
    查看软件的安装路径
    IP地址 网段的划分
    签名算法
    CentOS开启FTP及配置用户
    CentOS 5.5安装SVN(Subversion)
  • 原文地址:https://www.cnblogs.com/waw/p/2158751.html
Copyright © 2020-2023  润新知