241

I am trying to navigate between controllers using ActionLink. I will tell my problem with an example.

I am on Index view of Hat controller, and I am trying to use below code to create a link to Details action of Product controller.

<%= Html.ActionLink("Details", "Details", "Product", new { id=item.ID }) %>

Instead of creating a link to Details on Product controller, this generates a link to Details action under Hat controller and appends a Length parameter to the end of it:

Hat/Details/9?Length=7

I am not able to use HTML.ActionLink to switch between controllers because of this problem. I will appreciate if you can point me to what I am doing wrong. Thanks

PS: I am using the default route setting that comes with MVC

routes.MapRoute("Default", "{controller}/{action}/{id}", 
                     new { controller = "Home", action = "Index", id = "" } );
SteveC
  • 15,808
  • 23
  • 102
  • 173
kaivalya
  • 4,611
  • 4
  • 26
  • 28

9 Answers9

428

What you want is this overload :

//linkText, actionName, controllerName, routeValues, htmlAttributes
<%=Html.ActionLink("Details", "Details", 
    "Product", new {id = item.ID}, null) %>
Çağdaş Tekin
  • 16,592
  • 4
  • 49
  • 58
  • 1
    Can you explain why this particular overload works and korki's does not? How does setting htmlAttributes to null affect the routing of the link? – Derek Hunziker Aug 16 '10 at 16:26
  • 35
    It's because if you use the other parameters it assumes that the third argument is the routevalues and the 4th argument is the htmlattributes. Adding a 5th argument forces the method to use the correct overload. Flick through the overloads in intellisense and this will make more sense. – Banford Feb 22 '11 at 09:50
  • 2
    The overload of ActionLink are really clumsy. The whole point of accepting an 'object routeValues' instead of a RouteValueCollection is to reduce the amount of typing. However, you end up having to type an extra null. Non-intuitive and counter productive ... – TiMoch Jun 27 '13 at 09:10
  • 3
    I agree, the overload parameters are poorly designed.. I thought it was a bug for the longest time. I really had to stare a 9th time at all the intellisense to understand I was using the wrong signature – Bkwdesign Sep 18 '13 at 14:35
  • 2
    For future readers, if you hit this issue and you're trying to add a css style, this is the correct overload. @Html.ActionLink("MyText", "MyAction", "MyController", null, new { @class = "myClass" }) – granadaCoder Jan 21 '16 at 23:00
  • I was hitting my head against this for awhile before I realized that the htmlAttribute null parameter was not optional. Once I added it I hit the right overload and everything worked. – Matt West Apr 14 '17 at 18:24
19

With that parameters you're triggering the wrong overloaded function/method.

What worked for me:

<%= Html.ActionLink("Details", "Details", "Product", new { id=item.ID }, null) %>

It fires HtmlHelper.ActionLink(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)

I'm using MVC 4.

Cheerio!

Stephan Venter
  • 328
  • 2
  • 6
  • 3
    Your line of code does not trigger the overload you mention but HtmlHelper.ActionLink(string linkText, string actionName, object routeValues, object htmlAttributes). This yields the same result the OP was trying to avoid. You need to add an additional null parameter. – TiMoch Jun 27 '13 at 09:06
  • Thanks TiMoch, missed that one? – Stephan Venter May 06 '14 at 13:57
15

I would recommend writing these helpers using named parameters for the sake of clarity as follows:

@Html.ActionLink(
    linkText: "Details",
    actionName: "Details",
    controllerName: "Product",
    routeValues: new {
        id = item.ID
    },
    htmlAttributes: null
)
Bojan B
  • 2,091
  • 4
  • 18
  • 26
Psi-Ed
  • 683
  • 1
  • 9
  • 22
  • As of 2019, this feature is implemented in ReSharper by JetBrains. It's actually very helpful for this circumstance. – Jamie Jul 25 '19 at 18:13
10

If you grab the MVC Futures assembly (which I would highly recommend) you can then use a generic when creating the ActionLink and a lambda to construct the route:

<%=Html.ActionLink<Product>(c => c.Action( o.Value ), "Details" ) %>

You can get the futures assembly here: http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471

James Avery
  • 3,062
  • 1
  • 20
  • 26
  • Thanks for the actual link - was trying to find it! – Perhentian May 07 '09 at 11:41
  • 1
    Careful with this though as it's not been included in MVC2. The reasoning is that Actions are not necessarily Methods (which I agree with but it's going to be a pain to migrate as we've been using the generic method for a while now). Here's the full article on why it's not been kept in 2: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx – Stu Mar 30 '10 at 10:01
7

You're hitting the wrong the overload of ActionLink. Try this instead.

<%= Html.ActionLink("Details", "Details", "Product", new RouteValueDictionary(new { id=item.ID })) %>
Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
6

try it it is working fine

  <%:Html.ActionLink("Details","Details","Product",  new {id=item.dateID },null)%>
sandy barasker
  • 145
  • 1
  • 2
  • 8
3

An alternative solution would be to use the Url helper object to set the href attribute of an <a> tag like:

<a href="@Url.Action("Details", "Product",new { id=item.ID }) )">Details</a>
George Chondrompilas
  • 3,167
  • 27
  • 35
2

Note that Details is a "View" page under the "Products" folder.

ProductId is the primary key of the table . Here is the line from Index.cshtml

 @Html.ActionLink("Details", "Details","Products" , new  {  id=item.ProductId  },null)
AnotherOne
  • 78
  • 2
  • 11
0

this code worked for me in partial view:

<a href="/Content/Index?SubCategoryId=@item.Id">@item.Title</a>
Amin Saadati
  • 719
  • 8
  • 21
  • While this does work, it circumvents the entire point of using ActionLink... the entire point of ActionLink is to avoid manually typing the URL and the potential issues that can create – Jon Story Oct 24 '18 at 13:02