Reputation: 7345
Let's say I have this structure:
Home/
Index
About
Project/
Index
Details
How can I omit the controller name for Home views?
I want to write {root}/About
instead of {root}/Home/About
.
I also want {root}/Project/Details/2
to work.
Here is what I tried in RegisterRoutes
:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DefaultRoute",
url: "{controller}/{action}/{id}",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new
{
controller = "Home",
action = "Index"
}
);
Edit: I also tried swapping the order of my MapRoute
calls but it still doesn't work.
What I need is:
{root}/Home/Index > HomeController.Index
{root}/Home > HomeController.Index
{root} > HomeController.Index
{root}/Home/About > HomeController.About
{root}/About > HomeController.About
{root}/Project/Index > ProjectController.Index
{root}/Project > ProjectController.Index
{root}/Project/Details/12 > ProjectController.Details
Upvotes: 2
Views: 130
Reputation: 49095
Just change the order of your MapRoute
calls:
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The 'Default' route has to be defined last, otherwise it matches all Url patterns and no further routes are evaluated.
Update:
As per your edit, since you want to preserve the 'controller-name-only' route as well. Try this:
public class ActionExistsConstraint : IRouteConstraint
{
private readonly Type _controllerType;
public ActionExistsConstraint(Type controllerType)
{
this._controllerType = controllerType;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var actionName = values["action"] as string;
if (actionName == null || _controllerType == null || _controllerType.GetMethod(actionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase) == null)
return false;
return true;
}
}
Then:
routes.MapRoute(
name: "HomeRoute",
url: "{action}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { exists = new ActionExistsConstraint(typeof(HomeController)) }
);
See MSDN
Upvotes: 6