Reputation: 51052
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
set up the namespaces for the two routes so that the second one matches "anything but Admin"
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
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).
Upvotes: 2
Views: 1100
Reputation: 51052
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();
}
Upvotes: 1