I'm having difficulties with my controllers that are in an Area answering requests on routes that aren't for the area. So I have a setup like this (Extra stuff cut):
/Areas/Security/Controllers/MembersController.cs
/Areas/Security/SecurityAreaRegistration.cs
/Controllers/HomeController.cs
I have my area for security defined:
namespace MyApp.Web.Areas.Security
{
public class SecurityAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Security";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Security_default",
"Security/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
And my global routing rules:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*robotstxt}", new { robotstxt = @"(.*/)?robots.txt(/.*)?" });
routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MyApp.Web.Controllers" }
);
In my global asax I'm doing quite a few things but the relevant part is that I call AreaRegistration.RegisterAllAreas();
then I call the routing function that does the above.
But my problem is that requests for "/Members/" are hitting my Members controller using my "Default" route... even though the controller's not in the namespace I specified. Then when it tries to run it can't find it's Views cause they're defined in the Area and it's trying to find them in the overall Views folders. I tried making the route namespace "Weird.Namespace.With.No.Content"
and it STILL hits the Members controller - I can't find any way to make it not use that controller. How do I make it not answer requests that aren't in it's area?
Ended up finding a solution by changing the Route to:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "MyApp.Web.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;
For some reason with that unset it seemed to always find my Controllers no matter where they were and totally disregard my namespaces - even from other referenced assemblies. Looking through the ILSpy of DefaultControllerFactory
it looks like GetControllerType
eventually falls back to searching absolutely every controller if it doesn't find the controller in the namespaces you asked for...
This flag seems to be set automatically on the Routes I made in a specific area, but not on the ones I made globally. When I set it on the global ones they began behaving how I had originally expected. I have no idea why you'd ever want to turn this on...
You should register the namespace on your area as well.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Security_default",
"Security/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new []{ "MyApp.Web.Areas.Security.Controllers"},
);
}
And then make sure all your controllers are in their appropriate namespaces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With