Update:
I’ve found solution through using ActionConstraint. You have to add custom Action Constraint attribute about duplicate actions.
Example with duplicate Index methods.
First HomeController
namespace WebApplication.Controllers
{
public class HomeController : Controller
{
[NamespaceConstraint]
public IActionResult Index()
{
return View();
}
}
}
Second HomeController
namespace WebApplication
{
public class HomeController : Controller
{
[NamespaceConstraint]
public IActionResult Index()
{
return View();
}
}
}
Configure routing
app.UseMvc(cR =>
cR.MapRoute("default", "{controller}/{action}", null, null,
new { Namespace = "WebApplication.Controllers.HomeController" }));
Action constraint
namespace WebApplication
{
public class NamespaceConstraint : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
var dataTokenNamespace = (string)routeContext.RouteData.DataTokens.FirstOrDefault(dt => dt.Key == "Namespace").Value;
var actionNamespace = ((ControllerActionDescriptor)action).MethodInfo.DeclaringType.FullName;
return dataTokenNamespace == actionNamespace;
}
}
}
First answer:
Does attribute routing funk up the routes defined by app.UseMvc()?
Attribute routing and Convention-based routing (routes.MapRoute(...
) work independently. And attribute routes have advantage over convention routes.
but it doesn’t seem to do what I want. Is there a way to restrict the routing engine to a certain namespace?
Instead of using a list of namespaces to group your controllers we recommend using Areas. You can attribute your controllers (regardless of which assembly they are in) with a specific Area and then create a route for that Area.
You can see a test website that shows an example of using Areas in MVC 6 here: https://github.com/aspnet/Mvc/tree/dev/test/WebSites/RoutingWebSite.
Example using Area with convention-based routing
Controller:
//Reached through /admin/users
//have to be located into: project_root/Areas/Admin/
[Area("Admin")]
public class UsersController : Controller
{
}
Configure convention-based routing:
app.UseMvc(routes =>
{
routes.MapRoute(
"areaRoute",
"{area:exists}/{controller}/{action}",
new { controller = "Home", action = "Index" });
}
Example using Area with attribute-based routing
//Reached through /admin/users
//have to be located into: project_root/Areas/Admin/
[Area("Admin")]
[Route("[area]/[controller]/[action]", Name = "[area]_[controller]_[action]")]
public class UsersController : Controller
{
}