46

I have the following ActionLink in my view

<%= Html.ActionLink("LinkText", "Action", "Controller"); %>

and it creates the following URL http://mywebsite.com/Controller/Action

Say I add an ID at the end like so: http://mywebsite.com/Controller/Action/53 and navigate to the page. On this page I have the markup I specified above. Now when I look at the URL it creates it looks like this:

http://mywebsite.com/Controller/Action/53 (notice the addition of the ID)

But I want it to remove the ID and look like it did originally, like this http://mywebsite.com/Controller/Action (notice no ID here)

Any ideas how I can fix this? I don't want to use hard coded URLs since my controller/actions may change.

codette
  • 12,343
  • 9
  • 37
  • 38
  • 1
    See [this workitem](https://aspnetwebstack.codeplex.com/workitem/1346) for Microsoft's official explanation of this issue and workarounds. – NightOwl888 Jan 15 '16 at 09:14

9 Answers9

48

The solution is to specify my own route values (the fourth parameter below)

<%= Html.ActionLink("LinkText", "Action", "Controller", 
    new { id=string.Empty }, null) %>
Community
  • 1
  • 1
codette
  • 12,343
  • 9
  • 37
  • 38
  • Thanks for this answer, I needed it for another circumstance but you hit the nail right on the head with that trailing null! – Samurai Ken Dec 10 '09 at 16:10
  • This seems a little kludgey... I need to do the same thing but I think I might have to create a new extension method like Arnis L posted below – Jiho Han Mar 13 '10 at 15:20
  • 1
    Also this seems like the functionality should be built-in to the framework since this situation comes up often. For example, having a menu, you don't want the menu link to contain all of the parameters, just the action – Jiho Han Mar 13 '10 at 15:21
  • 1
    i m using .NET 4 and mvc2 but string.empty does not solve the above mentioned problem and actionlink still keeping the ambient values – Muhammad Adeel Zahid Aug 11 '10 at 06:35
13

It sounds like you need to register a second "Action Only" route and use Html.RouteLink(). First register a route like this in you application start up:

routes.MapRoute("ActionOnly", "{controller}/{action}", 
   new { controller = "Home", action = "Index" } );

Then instead of ActionLink to create those links use:

Html.RouteLink("About","ActionOnly")
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Brian Cauthon
  • 5,524
  • 2
  • 24
  • 26
  • +1 for using `Html.RouteLink()`. Worked for me - you can also specify routeValues so MVC loses the current action and goes back to the index or something, eg. `@Html.RouteLink("Cancel", "ThisSection_default", new { action = "Index" })`. – Jez Feb 11 '13 at 16:56
10

The problem is the built in methods take input from the URL you are currently on as well as what you supply. You could try this:

<%= Html.ActionLink("LinkText", "Action", "Controller", new { id = ""}) %>

That should manually wipe the id parameter.

Garry Shutler
  • 32,260
  • 12
  • 84
  • 119
4

If you either don't know what values need to be explicitly overridden or you just want to avoid the extra list of parameters you can use an extension method like the below.

<a href="@Url.Isolate(u => u.Action("View", "Person"))">View</a>

The implementation details are in this blog post

Steve Greatrex
  • 15,789
  • 5
  • 59
  • 73
4

Don't know why, but it didn't work for me (maybe because of Mvc2 RC). Created urlhelper method =>

 public static string
            WithoutRouteValues(this UrlHelper helper, ActionResult action,params string[] routeValues)
        {
            var rv = helper.RequestContext.RouteData.Values;
            var ignoredValues = rv.Where(x=>routeValues.Any(z => z == x.Key)).ToList();
            foreach (var ignoredValue in ignoredValues)
                rv.Remove(ignoredValue.Key);
            var res = helper.Action(action);
            foreach (var ignoredValue in ignoredValues)
                rv.Add(ignoredValue.Key, ignoredValue.Value);
            return res;
        }
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
  • I had the same problem (using MVC2 RTM). I had route value called `plan` and the last (default) route added it as `?plan=X`. So I added default value to the last (default) route for my `plan` route value as `plan = string.Empty`. Even though route definition doesn't define URL segment variable called `plan`. As long as it worked, I'm fine with it. – Robert Koritnik Feb 24 '11 at 19:58
  • I used a variation of this to reliably and elegantly resolve this issue. – John B Sep 07 '12 at 17:46
4

I explicitly set the action name as "Action/". Seems a little like a hack but it's a quick fix.

@Html.ActionLink("Link Name", "Action/", "Controller")
BorgRebel
  • 498
  • 3
  • 13
  • I had to do this as well, the link was to index, so I was able to use just "/" as the action. @Html.ActionLink("Link Name", "/", "Controller") – Derrick Apr 19 '16 at 23:30
3

Another way is to use ActionLink(HtmlHelper, String, String, RouteValueDictionary) overload, then there are no need to put null in the last parameter

<%= Html.ActionLink("Details", "Details", "Product", new RouteValueDictionary(new { id=item.ID })) %>
Murilo Lima
  • 245
  • 1
  • 4
  • 12
1

The overloads of Html.ActionLink are changed on the later versions of MVC. On MVC 5 and above. This is how to do this:

@Html.ActionLink("LinkText", "Action", "Controller", new { id = "" }, null)

Note I passed "" for id parameter and null for HTMLATTRIBUTES.

yogihosting
  • 5,494
  • 8
  • 47
  • 80
0

I needed my menu links to be dynamic. Rather than implement a lot of extra code and routing for every single page I simple dispensed with the HTML helper.

<a href="@(item.websiteBaseURL)/@(item.controller)/@(item.ViewName)">@item.MenuItemName</a>
nuander
  • 1,319
  • 1
  • 19
  • 33