2
votes

In my MVC application I have a default route defined:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new []{ "Demo.Controllers" }
);

I created a new Area called Admin and it added a route to in the AdminAreaRegistration class:

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Admin_default",
        "Admin/{controller}/{action}/{id}",
        new { action = "Index", controller = "Home", id = UrlParameter.Optional }
    );
} 

In my main _Layout file I tried to do the following:

@Html.RouteLink("Admin", "Admin_default")

It only works in certain cases (such as if I'm already in an Admin page). If I am in the /Home/About section of my site, then the URL gets generated like so:

/Admin/Home/About

If I am in my Index action of the Home controller (in the main area, not admin) then the URL gets generated like so:

/Admin

Why doesn't RouteLink work like I think it should using Areas in MVC?

3

3 Answers

3
votes

@Html.RouteLink("Admin", "Admin_default") this route uses the route with the name of Admin_default so it will always use that route to generate the url.

@Html.RouteLink("Admin", "Admin_default", new { controller = "Home", action = "Index" })

When you don't specify stuff like route values most of MVC uses the values that currently exist. In this case since the action and controller values are null it looks at the RouteValues and checks to see if they're there and if they're found they use the values found there instead.

This is sometimes helpful. For instance if you want {id} to be populated with the same value that was used on the page.

Url: /home/edit/1701

@Html.RouteLink("Refresh", "Default") would result in the same exact url - you can specify overrides if you want.

3
votes

I would also suggest not naming your routes. You can force yourself to do this by passing null to the route name arg when creating it.

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(null,
        "Admin/{controller}/{action}/{id}",
        new { action = "Index", controller = "Home", id = UrlParameter.Optional }
    );
}

You can then use RouteLink like so:

@Html.RouteLink("Admin", 
    new { controller = "Home", action = "Index", area = "Admin" })

Reply to comment

Wish I could say I came up with the idea. Learned this from Steve Sanderson's MVC book. There are a ton of method overloads that take a route name as a parameter (RouteLink, but also RedirectToRoute and others). Not using route names forces you to use other overloads of those methods, which IMO are more intuitive and easier to "get right".

1
votes

Naming your routes is not recommended since it creates dependencies in your view towards the existing routes. I suggest using a null value