Search code examples
c#.netasp.net-mvcasp.net-mvc-3asp.net-routing

Unable to make ActionLink or RouteLink generate the correct URL


I'm new to ASP.NET MVC (working with version 3) and cannot get ActionLink or RouteLink to work as I'm expecting. In this app, an event can have many activities and I wish to route to them using:

/Event/1/Activity
/Event/1/Activity/Index  (same as previous)
/Event/1/Activity/Details/5

The HTML generated by these two helpers always looks like:

/Event/1

Here's the code...

View Razor HTML

@Html.RouteLink("View Sessions", "SubControllerIndex",
    new { eventId = Model.Id, controller = "Activity", action = "Index" })
@Html.ActionLink("View Sessions", "Index", "Activity", new { eventId = Model.Id }, null)

Route mappings

routes.MapRoute(
    "SubControllerIndex",
    "Event/{eventId}/{controller}",
    new { controller = "Activity", action = "Index" },
    new { eventId = @"\d+" }
);
routes.MapRoute(
    "ActivityIndex",
    "Event/{eventId}/{controller}/{action}/{id}",
    new { controller = "Activity", action = "Index", id = UrlParameter.Optional },
    new { eventId = @"\d+", id = @"\d*" }
);
routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
    new { id = @"\d*" }
);

Activity controller

public ActionResult Index(long eventId)
{
    var activities = _context.Activities.Where(a => a.Event.Id == eventId).ToList();
    return View(activities);
}

Any ideas what I'm doing wrong here?


Solution

  • The reason that the routing system generates /Event/1 instead of /Event/1/Activity/Index for the route

    routes.MapRoute(
       "ActivityIndex",
       "Event/{eventId}/{controller}/{action}/{id}",
       new { controller = "Activity", action = "Index", id = UrlParameter.Optional },
       new { eventId = @"\d+", id = @"\d*" }
    );
    

    is because when generating urls the system will not include any default values in the url. In this case the default value of controller is Activity and the default value of action is Index. Thus,

    @Html.RouteLink("View Sessions", "SubControllerIndex",
        new { eventId = Model.Id, controller = "Activity", action = "Index" })
    

    will generate /Event/1 instead of /Event/1/Activity/Index. If you click on the link you should still go to the Index action method on the ActivityController.