使用xml文件来动态配置Asp.net mvc的Route规则

一般情况下,我们都是直接在Global.asax.cs文件中直接写上Route规则的,例如:
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",                                              // Route name
        
"{controller}/{action}/{id}",                           // URL with parameters
        
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
   
);
}这样在我们的程序编译、部署后,我们想修改这个Route规则就得重新修改程序中Global.asax.cs文件中的Route规则=>编译=>部署,不可以做到动态配置。
其实我们可以做到动态配置,我们可以将这个Route规则写到一个XML文件中,例如这样:
<RouteConfiguration>
  <
ignore>
    <!--
忽略对.axd文件的Route,直接处理-->
    <
add url="{resource}.axd/{*pathInfo}" >
      <
constraints>
        <!--
添加约束,value是乱写的,只为演示-->
        <
add name="resource" value="\w" />
      </
constraints>
    </
add>
  </
ignore>
  <
map>
    <
route name="Post" url="Post/{id}" controller="Home" action="Post" >
      <
parameters>
        <!--
添加参数默认值-->
        <!--
添加约束,id必须为GUID-->
        <
add name="id" value="" constraint="[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}" />
      </
parameters>
    </
route>
    <
route name="Default" url="{controller}/{action}/{id}" controller="Home" action="Index" >
      <
parameters>
        <
add name="id" value="" />
      </
parameters>
    </
route>
  </
map>
</
RouteConfiguration>我们例如Web.config中的configSection来写我们的自定义配置节,来配置上面的XML文件。首先,我需要写一个定义的configSection,他继承自ConfigurationSection,如下:
public class MvcRouteConfigurationSection : ConfigurationSection
{
    [ConfigurationProperty("ignore", IsRequired=false)]
    public IgnoreCollection Ignore
    {
        get
        
{
            return (IgnoreCollection)(this["ignore"]);
        }
    }

    [ConfigurationProperty("map", IsRequired=false)]
    public RoutingCollection Map
    {
        get
        
{
            return (RoutingCollection)(this["map"]);
        }
    }
}然后我们写一个扩展方法来自定义将我们配置好的Route规则写入到程序路由表中:
public static void MapRoute(
    this System.Web.Routing.RouteCollection routes,
    MvcRouteConfigurationSection section )
{
    // Manipulate the Ignore List
   
foreach(IgnoreItem ignoreItem in section.Ignore)
    {
        RouteValueDictionary ignoreConstraints = new RouteValueDictionary();

        foreach (Constraint constraint in ignoreItem.Constraints)
            ignoreConstraints.Add(constraint.Name, constraint.Value);

        IgnoreRoute(routes, ignoreItem.Url, ignoreConstraints);
    }

    // Manipluate the Routing Table
   
foreach (RoutingItem routingItem in section.Map)
    {
        RouteValueDictionary defaults = new RouteValueDictionary();
        RouteValueDictionary constraints = new RouteValueDictionary();

        if (routingItem.Controller != string.Empty)
            defaults.Add("controller", routingItem.Controller);

        if (routingItem.Action != string.Empty)
            defaults.Add("action", routingItem.Action);

        foreach (Parameter param in routingItem.Paramaters)
        {
            defaults.Add(param.Name, param.Value);
            if (!string.IsNullOrEmpty(param.Constraint))
            {
                constraints.Add(param.Name, param.Constraint);
            }
        }

        MapRoute(routes, routingItem.Name, routingItem.Url, defaults, constraints);
    }
}
然后在web.config中的configSections配置节下加入我们写好的MvcRouteConfigurationSection
<section name="RouteConfiguration" type="MvcXmlRouting.MvcRouteConfigurationSection"/>最后,在Global.asax.cs中用我们刚才写的MapRoute扩展方法来注册我们的Route规则:
public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        MvcRouteConfigurationSection section =
            (MvcRouteConfigurationSection)ConfigurationManager.GetSection("RouteConfiguration");

        routes.MapRoute(section);
    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
    }
}