2

我正在将现有应用程序从 ASP.NET webforms 移动到 ASP.NET MVC。

在 admin 目录和 public 目录下都有一些页面名称,例如 /help/ 和 /admin/help/

命名空间与目录结构相匹配,因此 /help 页面将在 MyApplication.Help 中,而 /admin/help 将在 MyApplication.Admin.Help 中。我想为控制器保留该设置,所以理想情况下我想拥有 MyApplication.Help.HelpController 和 MyApplication.Admin.Help.HelpController。

我已经设置了这样的路线

    routes.MapRoute(
      "Admin",
        // Route name
      "admin/{controller}/{action}/{id}",
        // URL with parameters
      new { controller = "Home", action = "Index", id = "" },
        // Parameter defaults
    new []{"MyApplication.Admin.*"}
        //namespaces to find controller in
    ).DataTokens["UseNamespaceFallback"] = false;

    routes.MapRoute(
      "Default",
        // Route name
      "{controller}/{action}/{id}",
        // URL with parameters
      new { controller = "Home", action = "Index", id = "" },
        // Parameter defaults
    new [] { "MyApplication.*" }
        //namespaces to find controller in
    ).DataTokens["UseNamespaceFallback"] = false;

使用此设置,/admin/help 路由工作正常,但 /help 路由失败,抱怨多个类型与名为“help”的控制器匹配(因为 MyApplication.Help.HelpController 和 MyApplication.Admin.Help.HelpController 显然都匹配MyApplication.* 我给出的命名空间)。

是否有可能

  1. 为两条路由设置命名空间,以便第二条匹配“除了管理员之外的任何东西”

  2. 为两条路线设置命名空间,以便第二条路线仅在有一层文件夹但没有两层时匹配,或者

  3. 编写一个自定义方法,告诉路由在哪个命名空间中查找控制器(这样我就可以自己实现这个逻辑)?

不幸的是,更改文件夹层次结构(例如,将所有非管理页面放在“公共”文件夹/命名空间下)不是一种选择(因为我正在逐步迁移到 MVC,因此某些页面仍然用作 Web 表单)。

4

1 回答 1

1

所以这就是我最终要做的,至少现在是这样。对于非管理员路由,我创建了一个方法,该方法将列出所有适当的命名空间并在应用程序启动时将它们注册到路由中。大概这会在一定程度上减慢应用程序的启动速度,但我看不出有什么不同。

如果有人有更好的方法,我很高兴听到。

routes.MapRoute(
  "Admin",
    // Route name
  "admin/{controller}/{action}/{id}",
    // URL with parameters
  new { controller = "Home", action = "Index", id = "" },
    // Parameter defaults
new []{"MyApplication.Admin.*"}
    //namespaces to find controller in
).DataTokens["UseNamespaceFallback"] = false;

routes.MapRoute(
  "Default",
    // Route name
  "{controller}/{action}/{id}",
    // URL with parameters
  new { controller = "Home", action = "Index", id = "" },
    // Parameter defaults
GetNonAdminNamespaces()
    //namespaces to find controller in
).DataTokens["UseNamespaceFallback"] = false;


  private static string[] GetNonAdminNamespaces()
  {
      var namespaces = new HashSet<string>();
      System.Type[] allTypes =  Assembly.GetCallingAssembly().GetTypes();
      foreach (var item in allTypes)
      {
          string ns = item.Namespace;
          if ( !string.IsNullOrEmpty(ns) && ns.StartsWith("MyApplication.") && !ns.StartsWith("MyApplication.Admin."))
          {
              namespaces.Add(ns);
          }
      }
      return namespaces.ToArray();
  }
于 2013-03-26T13:38:39.433 回答