155

In ASP.NET MVC, I'm trying to create a link that includes an anchor tag (that is, directing the user to a page, and a specific section of the page).

The URL I am trying to create should look like the following:

<a href="/category/subcategory/1#section12">Title for a section on the page</a>

My routing is set up with the standard:

routes.MapRoute("Default", "{controller}/{action}/{categoryid}"); 

The action link syntax that I am using is:

<%foreach (Category parent in ViewData.Model) { %>
<h3><%=parent.Name %></h3>
<ul>
<%foreach (Category child in parent.SubCategories) { %>
    <li><%=Html.ActionLink<CategoryController>(x => x.Subcategory(parent.ID), child.Name) %></li>
<%} %>
</ul>
<%} %>

My controller method is as follows:

public ActionResult Subcategory(int categoryID)
{
   //return itemList

   return View(itemList);
}

The above correctly returns a URL as follows:

<a href="/category/subcategory/1">Title for a section on the page</a>

I can't figure out how to add the #section12 part. The "section" word is just the convention I am using to break up the page sections, and the 12 is the ID of the subcategory, i.e., child.ID.

How can I do this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dp.
  • 8,138
  • 7
  • 33
  • 28

7 Answers7

286

There are overloads of ActionLink which take a fragment parameter. Passing "section12" as your fragment will get you the behavior you're after.

For example, calling LinkExtensions.ActionLink Method (HtmlHelper, String, String, String, String, String, String, Object, Object):

<%= Html.ActionLink("Link Text", "Action", "Controller", null, null, "section12-the-anchor", new { categoryid = "blah"}, null) %>
Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622
Brad Wilson
  • 67,914
  • 9
  • 74
  • 83
  • 1
    Are these overloads part of an extensions library? I don't seem to get them. – grenade Sep 18 '09 at 13:12
  • There are two: public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes); public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary htmlAttributes); – Brad Wilson Sep 26 '09 at 16:26
  • 1
    The overloads of Html.ActionLink that allow specification of an anchor by passing the fragment, force you to pass the controller by name. I don't like that. If the controller name is incorrect, run-time exceptions will occur, rather than a compile errors. – R. Schreurs Jan 25 '13 at 12:26
  • @BradWilson What about RedirectToAction support for anchors? – mxmissile Feb 21 '13 at 15:07
  • This doesn't work if your "Link Text" is more than just text, unfortunately. – Robert McKee Feb 22 '13 at 18:15
  • 1
    @RobertMcKee if your link text is more than just text, then `Html.ActionLink()` wouldn't work in any scenario - you would need to use `href=@Url.Action()` style syntax. – Katstevens Nov 02 '17 at 12:56
  • @R.Schreurs you can avoid this behaviour by passing `null` for the controller name, and it will default to the controller specified in the current route, solving that problem – Katstevens Nov 02 '17 at 12:57
  • @Katstevens Correct, no implementation of Html.ActionLink would work, but using Url.Action like the accepted answer would, and .Net Core versions have a fragment overload too: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.urlhelperextensions.action?view=aspnetcore-6.0#Microsoft_AspNetCore_Mvc_UrlHelperExtensions_Action_Microsoft_AspNetCore_Mvc_IUrlHelper_System_String_System_String_System_Object_System_String_System_String_System_String_ – Robert McKee Dec 28 '21 at 21:28
103

I would probably build the link manually, like this:

<a href="<%=Url.Action("Subcategory", "Category", new { categoryID = parent.ID }) %>#section12">link text</a>
LorenzCK
  • 7,411
  • 2
  • 36
  • 28
  • 20
    Should really use the overloads for ActionLink as described by @Brad Wilson. – mattruma Feb 20 '10 at 13:40
  • 19
    @mattruma sorry I disagree. KISS. Why have a member full of parameters , some of which are left as null, when you can simply state it explicitly. Anyone can see what the above means whereby Brad's response is convoluted and requires you to dig into intellisense. Too many parameters is a recognised anti pattern..http://c2.com/cgi/wiki?TooManyParameters – Ed Blackburn Feb 01 '12 at 14:51
  • 2
    I agree. Both methods work, but since the way fragments are specified in URLs isn't going to change in the near future, I think this way is actually more readable and clearer in its intent. If needed, you can still extend the `Url` or `Html` object with a custom method which includes a simple way to add a fragment string. – LorenzCK Feb 03 '12 at 14:03
17

I don't remember in which version of ASP.NET MVC (ASP.NET MVC 3+ I believe) / Razor the parameterlabeldeclaration or whatever it's called (parameter: x) feature was introduced, but to me this is definitely the proper way to build a link with an anchor in ASP.NET MVC.

@Html.ActionLink("Some link text", "MyAction", "MyController", protocol: null, hostName: null, fragment: "MyAnchor", routeValues: null, htmlAttributes: null)

Not even Ed Blackburns antipattern argument from this answer can compete with that.

Community
  • 1
  • 1
PussInBoots
  • 11,028
  • 9
  • 52
  • 84
  • 1
    Literally this saved my life. Attributing your post as my solution here http://stackoverflow.com/questions/32420028/how-to-create-dropdown-navbar-menu-item-in-layout-cshtml-in-asp-net . – Matthew Sep 06 '15 at 16:28
15

I just did it like this:

<a href="@Url.Action("Index","Home")#features">Features</a>
Zapnologica
  • 22,170
  • 44
  • 158
  • 253
1

Here is the real life example

@Html.Grid(Model).Columns(columns =>
    {
           columns.Add()
                   .Encoded(false)
                   .Sanitized(false)
                   .SetWidth(10)
                   .Titled(string.Empty)
                   .RenderValueAs(x => @Html.ActionLink("Edit", "UserDetails", "Membership", null, null, "discount", new { @id = @x.Id }, new { @target = "_blank" }));

  }).WithPaging(200).EmptyText("There Are No Items To Display")

And the target page has TABS

<ul id="myTab" class="nav nav-tabs" role="tablist">

        <li class="active"><a href="#discount" role="tab" data-toggle="tab">Discount</a></li>
    </ul>
NoWar
  • 36,338
  • 80
  • 323
  • 498
0

I Did that and it works for redirecting to other view I think If you add the #sectionLink after It will work

<a class="btn yellow" href="/users/Create/@Model.Id" target="_blank">
                                        Add As User
                                    </a>
Ahmed Samir
  • 117
  • 4
0

My solution will work if you apply the ActionFilter to the Subcategory action method, as long as you always want to redirect the user to the same bookmark:

http://spikehd.blogspot.com/2012/01/mvc3-redirect-action-to-html-bookmark.html

It modifies the HTML buffer and outputs a small piece of javascript to instruct the browser to append the bookmark.

You could modify the javascript to manually scroll, instead of using a bookmark in the URL, of course!

Hope it helps :)

Spikeh
  • 3,540
  • 4
  • 24
  • 49