我需要像这样映射URL:
/股票/风险 --> StockRiskController.Index()
股票/风险/吸引力 --> StockRiskController.Attr()
摇滚/风险/图表 --> StockRiskController.Chart()
。
/债券/业绩 --> BondPerformanceController.Index()
债券/性能/吸引力 --> BondPerformanceController.Attr()
债券/业绩/图表 --> BondPerformanceController.Chart()
...
第一部分是动态的,但可枚举,第二部分只有两个选项(风险|性能)。
目前我只知道两种方式:
- 自定义控制器工厂(似乎矫枉过正或复杂)
- 对所有组合进行硬编码,因为它们是可枚举的(丑陋的)。
我可以使用routes.MapRoute
来实现此目的吗?还是其他方便的方法?
有一个基于 IRouteConstraint
的不错解决方案。首先,我们必须创建新的路由映射:
routes.MapRoute(
name: "PrefixedMap",
url: "{prefix}/{body}/{action}/{id}",
defaults: new { prefix = string.Empty, body = string.Empty
, action = "Index", id = string.Empty },
constraints: new { lang = new MyRouteConstraint() }
);
下一步是创建约束。在我将介绍一些如何检查相关性的方法之前,如上所述 - 两个具有可能值的列表,但逻辑可以调整
public class MyRouteConstraint : IRouteConstraint
{
public readonly IList<string> ControllerPrefixes = new List<string> { "stock", "bond" };
public readonly IList<string> ControllerBodies = new List<string> { "risk", "performance" };
...
现在是 Match 方法,它将根据需要调整路由
public bool Match(System.Web.HttpContextBase httpContext
, Route route, string parameterName, RouteValueDictionary values
, RouteDirection routeDirection)
{
// for now skip the Url generation
if (routeDirection.Equals(RouteDirection.UrlGeneration))
{
return false;
}
// try to find out our parameters
string prefix = values["prefix"].ToString();
string body = values["body"].ToString();
var arePartsKnown =
ControllerPrefixes.Contains(prefix, StringComparer.InvariantCultureIgnoreCase) &&
ControllerBodies.Contains(body, StringComparer.InvariantCultureIgnoreCase);
// not our case
if (!arePartsKnown)
{
return false;
}
// change controller value
values["controller"] = prefix + body;
values.Remove("prefix");
values.Remove("body");
return true;
}
你可以更多地使用这种方法,但现在概念应该很清楚了。
注意:我喜欢你的方法。有时,扩展/调整路由然后转到代码并"修复名称"更为重要。类似的解决方案在这里工作:动态修改路由值字典