0

I have the simplest setup:

An empty asp.net MVC application with one controller:

public class HomeController : Controller
{
    public ActionResult Edit(int id)
    {
        return View();
    }

    public ActionResult Commit(int id)
    {
        return View();
    }
}

My Edit.cshtml has a call to ActionLink() like so:

@Html.ActionLink("Commit Data", "Commit")

If I now access the Edit-Action through "/Home/Edit/2" I would expect that the rendered link directs the user to "/Home/Commit/2".

It does not :( ... The link is created to "Home/Commit", completely disregarding the current RouteData entries.

I am using the default routing configuration (have not added any routes).

One way to fix this would be to add an explicit route for both actions:

        routes.MapRoute(
                name: null,
                url: "Home/Edit/{id}",
                defaults: new { controller = "Home", action = "Edit" }
        );

        routes.MapRoute(
                name: null,
                url: "Home/Commit/{id}",
                defaults: new { controller = "Home", action = "Commit" }
        );

        routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

This works - but I really dont want to explicitly define every single route in the app - if I am using the "default" pattern...

The second solution would be to just add the routing-values manually like so:

@Html.ActionLink("Commit Data", "Commit", "Home", new {id = Model.Id})

But this also seems not right - ActionLink SHOULD use the current routing information, should it not?

What am I missing?

tereško
  • 58,060
  • 25
  • 98
  • 150
Wolfgang
  • 2,188
  • 1
  • 25
  • 24
  • you are not passing it any id in action link – Ehsan Sajjad Aug 02 '14 at 12:56
  • I am under the impression that asp.net mvc should figure that out by itself... after all I am currently on the "Edit"-action for id 2 and want to navigate to the "Commit"-action for id 2 – Wolfgang Aug 02 '14 at 15:14
  • And what if you were editing `Employee` with `ID = 2` who is an employee of `Organisation` with `ID = 1` and wanted an action link to an index page displaying all employees for the employees organisation. By your logic, this would display all employees for a different organisation (for `Organisation.ID = 2`). MVC's good, but not psychic. You need to do its as per your second olution. –  Aug 03 '14 at 03:24
  • I can follow your reasoning. But if you take a look at my first possible solution (adding explicit routes): Why is MVC suddenly "psychic" as you call it when I do that? The routes are just concrete "implementations" of the default route anyway. – Wolfgang Aug 03 '14 at 16:34
  • @Wolfgang - the reason is that the default route has the ID as optional... while your other two routes do not. You could probably get around this by having two sets of routes, one with optional parameters and one without. However, you would need to add a constraint that would select the non-optional route if the ID field has a value so that the correct route was selected. – Erik Funkenbusch Aug 03 '14 at 18:05
  • Thank you Erik - you are right... I could just implement a custom constraint which checks for the ID. It's really cool in how many ways MVC is extensible. Well - my confusion has subsided and I went with the solution I described below. Maybe its "right", maybe it isn't. Right now I like it and it works ;-) – Wolfgang Aug 04 '14 at 05:12

1 Answers1

0

Ok, in case someone else is wondering the same thing - or just wants to have a solution that works...

I simply created my own @ActionLink() helper method on my custom ViewPage base class:

    protected MvcHtmlString ActionLink(string linkText, string actionName)
    {
        var routeData = ViewContext.RequestContext.RouteData;

        var id = routeData.Values["id"];

        if (id != null)
            return Html.ActionLink(linkText, actionName, new {id = id});

        return Html.ActionLink(linkText, actionName);
    }

This is exactly what I wanted. Now I can call

@ActionLink("Commit", "Commit")

and when I'm in the context of something with an id, the link will point to the appropriate route for this Id.

Wolfgang
  • 2,188
  • 1
  • 25
  • 24