@Html.ActionLink is not linking to current area by default

565 views Asked by At

I have 2 areas Admin and FrontEnd (in that order).

When I am in a view in my FrontEnd area, ActionLink always points to the Admin area:

@Html.ActionLink("Checkout", "Address", "Checkout")

Will be http://localhost:53600/admin/Checkout/Address but the Checkout controller is in my FrontEnd area.

I know I can solve this by specifying a routedata object in the action link and setting area = "FrontEnd" but I don't want to. I want the ActionLink helper to default to my current route.

Is this possible?

All the questions I've read on actionlink are people asking how to link to another area which indicates it defaults to the current area for them. Am I alone with this issue?

Edit, these are my routes which you can see are tied to the correct namespace:

Admin

public void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute(
        "Administration_default",
        "admin/{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", area = "Administration", id = UrlParameter.Optional },
        new[] { "CC.Web.Areas.Administration.Controllers" }
        );
}

FrontEnd

public void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute("Default",
        "{controller}/{action}/{id}",
        new {controller = "Home", action = "Index", area = "FrontEnd", id = UrlParameter.Optional},
        new[] {"CC.Web.Areas.FrontEnd.Controllers"}
        );
}
1

There are 1 answers

1
Daniel J.G. On BEST ANSWER

Areas should be registered in classes deriving from AreaRegistration overriding the method void RegisterArea(AreaRegistrationContext context), see the msdn.

The AreaRegistrationContext defines its own methods to register area routes that will add the required dataTokens for the areas that are used when generating links and urls:

public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces)
{
    if (namespaces == null && Namespaces != null)
    {
        namespaces = Namespaces.ToArray();
    }

    Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
    route.DataTokens[RouteDataTokenKeys.Area] = AreaName;

    // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up
    // controllers belonging to other areas
    bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
    route.DataTokens[RouteDataTokenKeys.UseNamespaceFallback] = useNamespaceFallback;

    return route;
}

It also looks like the FrontEnd shouldn't be an area, so you could just have the standard MVC controllers and views (instead of the fronteand area) with an extra Admin area:

public class AdminAreaRegistration : AreaRegistration
{
    public override string AreaName
    {
        get
        {
            return "Administration";
        }
    }

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Administration_default",
            "admin/{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "CC.Web.Areas.Administration.Controllers" }
        );
    }
}

Remember that you should be calling AreaRegistration.RegisterAllAreas(); at the beggining of your main RegisterRoutes method invoked on app start.