將路由規則、URL 重寫規則等遷移出 Global.asax 代碼,存放於 web.config 專屬區段,實現「配置即代碼、熱更新無需重編譯」。本文示範完整實作流程。
ConfigurationSection:根區段,對應 <routeConfig>ConfigurationElementCollection:集合元素,對應 <routes>ConfigurationElement:單一路由元素,屬性映射 name, url, controller, action, constraints<configuration>
<configSections>
<section name="routeConfig"
type="Core.Configuration.Operation.RouteConfigSection, Core.Configuration" />
</configSections>
<routeConfig configSource="config\routes.config" /> <!-- 外部檔案,支援熱更新 -->
</configuration>
<routeConfig>
<routes>
<add name="Product" url="Product/{id}" controller="Product" action="Details"
constraints="id=\d+" />
<add name="Blog" url="Blog/{year}/{month}" controller="Blog" action="Archive"
constraints="year=\d{4};month=\d{2}" />
</routes>
</routeConfig>
public class RouteConfigSection : ConfigurationSection {
[ConfigurationProperty("routes")]
public RouteElementCollection Routes => (RouteElementCollection)base["routes"];
}
[ConfigurationCollection(typeof(RouteElement), AddItemName="add")]
public class RouteElementCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() => new RouteElement();
protected override object GetElementKey(ConfigurationElement element)
=> ((RouteElement)element).Name;
}
public class RouteElement : ConfigurationElement {
[ConfigurationProperty("name", IsRequired=true, IsKey=true)]
public string Name { get => (string)base["name"]; set => base["name"] = value; }
[ConfigurationProperty("url", IsRequired=true)]
public string Url { get => (string)base["url"]; set => base["url"] = value; }
[ConfigurationProperty("controller", IsRequired=true)]
public string Controller { get => (string)base["controller"]; set => base["controller"] = value; }
[ConfigurationProperty("action", IsRequired=true)]
public string Action { get => (string)base["action"]; set => base["action"] = value; }
[ConfigurationProperty("constraints", DefaultValue="")]
public string Constraints { get => (string)base["constraints"]; set => base["constraints"] = value; }
}
protected void Application_Start() {
var section = (RouteConfigSection)ConfigurationManager.GetSection("routeConfig");
foreach (RouteElement elem in section.Routes) {
var constraints = ParseConstraints(elem.Constraints); // 解析 "id=\d+" → RouteValueDictionary
RouteTable.Routes.MapRoute(elem.Name, elem.Url,
new { controller = elem.Controller, action = elem.Action }, constraints);
}
}
routes.config 立即生效(ASP.NET 自動重啟應用域)。configSource 指向各自配置檔。namespaces、dataTokens、handler 等進階屬性。IRouteConstraint 型別名稱,動態載入約束類別。