2

I'm moving an existing application from ASP.NET webforms to ASP.NET MVC.

There are some page names that exist both under the admin directory and in the public directory, e.g. /help/ as well as /admin/help/

The namespacing matches the directory structure, so the /help page will be in MyApplication.Help, while the /admin/help will be in MyApplication.Admin.Help. I'd like to keep that setup for the controllers, so ideally I'd like to have MyApplication.Help.HelpController and MyApplication.Admin.Help.HelpController.

I've set up routes like so

    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;

With this setup, the /admin/help route works fine, but the /help route fails, complaining that multiple types match the controller called "help" (because both MyApplication.Help.HelpController and MyApplication.Admin.Help.HelpController apparently match the MyApplication.* namespace I've given).

Is it possible to either

  1. set up the namespaces for the two routes so that the second one matches "anything but Admin"

  2. set up the namespaces for the two routes so that the second one only matches when there's a single layer of folders but not two layers, or

  3. write a custom method that tells the route what namespace to look in for the controller (so I can implement this logic myself)?

Unfortunately changing the folder heirarchy (e.g. put all of the non-admin pages under a "Public" folder/namespace) isn't an option (because I'm moving incrementally to MVC, so some pages are still served as webforms).

1
  • I remembered that ASP.NET MVC has source available, so I'm looking at the DefaultControllerFactory. Unfortunately I think the answer to my "is it possible" question is "no" -- the logic for matching the namespace is in an internal method in the ControllerTypeCache. I think I would have to write a completely custom ControllerFactory. But I'll leave this up in case someone has a better idea. Commented Mar 25, 2013 at 16:32

1 Answer 1

1

So here's what I ended up doing, at least for now. For the non-admin route, I created a method that will list all of the appropriate namespaces and register them with the route at application startup. Presumably that is slowing down application startup somewhat, but I can't perceive a difference.

If anyone has a better approach, I'm happy to hear it.

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();
  }
Sign up to request clarification or add additional context in comments.

1 Comment

Following up to say that, for various reasons, I actually did end up writing a custom controller factory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.