【发布时间】:2011-02-25 11:15:21
【问题描述】:
以下路由Page/View/Id 将转到页面控制器中的View 方法。我也想要以下路线:
/{page-title}
使用相同的方法。这样我就可以拥有如下 URL:
http://www.mysite.com/This-Is-a-Page
考虑到This-Is-a-Page 也可能是控制器,我该如何配置?
【问题讨论】:
标签: c# asp.net-mvc
以下路由Page/View/Id 将转到页面控制器中的View 方法。我也想要以下路线:
/{page-title}
使用相同的方法。这样我就可以拥有如下 URL:
http://www.mysite.com/This-Is-a-Page
考虑到This-Is-a-Page 也可能是控制器,我该如何配置?
【问题讨论】:
标签: c# asp.net-mvc
如果您的“控制器”路由和“页面”路由(见下文)使用相同的/something,那么您将必须实施以下规则:
在您的路线顶部:
route. MapRoute(
"ControllerRoute"
"{controller}",
new { controller = "Home", action = "Index" }
new { controller = GetControllerNameRegex() }
);
route.MapRoute(
"PageRoute",
"{pageSlug}"
new { controller = "Page", action = "ShowPage" }
);
由于您不能真正以编程方式执行后者,但you can do the former programmatically,您可以为您的控制器路由添加自定义约束,这样只有在您碰巧键入控制器名称时才会触发:
private static string GetControllerNameRegex()
{
var controllerNamesRegex = new StringBuilder();
List<string> controllers = GetControllerNames();
controllers.ForEach(s =>
controllerNamesRegex.AppendFormat("{0}|", s));
return controllerNamesRegex.ToString().TrimEnd('|');
}
private static List<Type> GetSubClasses<T>()
{
return Assembly.GetCallingAssembly().GetTypes().Where(type =>
type.IsSubclassOf(typeof(T))).ToList();
}
public List<string> GetControllerNames()
{
List<string> controllerNames = new List<string>();
GetSubClasses<Controller>().ForEach(type => controllerNames.Add(type.Name));
return controllerNames;
}
注意:最好的办法是确保没有任何以您的控制器命名的页面,您可以使用上述代码在运行时强制执行。
【讨论】:
您也许可以像这样添加一个全部捕获(将其放在默认路由之后):
routes.MapRoute(
null,
"{*query}",
new { controller = "SomeController", action = "SomeAction" }
);
动作签名如下所示:
public ActionResult(string query)
【讨论】: