如何分隔具有相同路径但执行不同操作的路径?

时间:2010-04-07 10:14:43

标签: c# asp.net-mvc

以下路由Page/View/Id将转到页面控制器中的View方法。我也想要以下路线:

/{page-title}

转到相同的方法。这样我就可以拥有以下网址:

http://www.mysite.com/This-Is-a-Page

如何配置此项,考虑This-Is-a-Page也可能是控制器?

2 个答案:

答案 0 :(得分:4)

如果你的“控制器”路线和“页面”路线(见下文)都使用相同的/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,您可以向控制器路由添加自定义约束,以便只有在您键入控制器名称时才会触发: / p>

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;
}
  

NB :最好的方法是确保不要在控制器之后命名任何页面,并且可以使用上面的代码在运行时强制执行。

答案 1 :(得分:0)

您可以添加一个catch all,就像这样(将它放在默认路由之后):

routes.MapRoute(
    null,
    "{*query}",
    new { controller = "SomeController", action = "SomeAction" }
);

动作签名看起来像这样:

public ActionResult(string query)