MegaMatt
MegaMatt

Reputation: 23763

Putting HTML inside Html.ActionLink(), plus No Link Text?

I have two questions:

  1. I'm wondering how I can display no link text when using Html.ActionLink() in an MVC view (actually, this is Site.Master).

There is not an overloaded version that does not allow link text, and when I try passing in just a blank string, the compiler tells me it needs a non-empty string.

How can I fix this?

  1. I need to put <span> tags within the anchor tag, but it's not working with Html.ActionLink();. I'd like to see the following output:

    Span text

How can I put tags inside of the anchor tag in ASP.NET MVC?

Upvotes: 179

Views: 186019

Answers (12)

RainyTears
RainyTears

Reputation: 189

please try this code:

@Html.Raw(@Html.ActionLink("text", "ActionName", "ControllerName", null, new { area = "Home" }).ToHtmlString().Replace("text", "<i class='fa fa-car sub-icon-mg' aria-hidden='true'></i> <span class='mini-sub-pro'>Link Text</span>"))

Upvotes: 0

barrypicker
barrypicker

Reputation: 10088

I ended up with a custom extension method. Its worth noting, when trying to place HTML inside of an Anchor object, the link text can be either to the left, or to the right of the inner HTML. For this reason, I opted to provide parameters for left and right inner HTML - the link text is in the middle. Both left and right inner HTML are optional.

Extension Method ActionLinkInnerHtml:

    public static MvcHtmlString ActionLinkInnerHtml(this HtmlHelper helper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues = null, IDictionary<string, object> htmlAttributes = null, string leftInnerHtml = null, string rightInnerHtml = null)
    {
        // CONSTRUCT THE URL
        var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
        var url = urlHelper.Action(actionName: actionName, controllerName: controllerName, routeValues: routeValues);

        // CREATE AN ANCHOR TAG BUILDER
        var builder = new TagBuilder("a");
        builder.InnerHtml = string.Format("{0}{1}{2}", leftInnerHtml, linkText, rightInnerHtml);
        builder.MergeAttribute(key: "href", value: url);

        // ADD HTML ATTRIBUTES
        builder.MergeAttributes(htmlAttributes, replaceExisting: true);

        // BUILD THE STRING AND RETURN IT
        var mvcHtmlString = MvcHtmlString.Create(builder.ToString());
        return mvcHtmlString;
    }

Example of Usage:

Here is an example of usage. For this example I only wanted the inner html on the right side of the link text...

@Html.ActionLinkInnerHtml(
    linkText: "Hello World"
        , actionName: "SomethingOtherThanIndex"
        , controllerName: "SomethingOtherThanHome"
        , rightInnerHtml: "<span class=\"caret\" />"
        )

Results:

this results in the following HTML...

<a href="/SomethingOtherThanHome/SomethingOtherThanIndex">Hello World<span class="caret" /></a>

Upvotes: 3

Ahsanul
Ahsanul

Reputation: 215

Please try below Code that may help you.

 @Html.ActionLink(" SignIn", "Login", "Account", routeValues: null, htmlAttributes: new {  id = "loginLink" ,**@class="glyphicon glyphicon-log-in"** }) 

Upvotes: 0

Carlos Toledo
Carlos Toledo

Reputation: 2684

My solution using bootstrap components:

<a class="btn btn-primary" href="@Url.Action("resetpassword", "Account")">
    <span class="glyphicon glyphicon-user"></span> Reset Password
</a>

Upvotes: 0

dbarth
dbarth

Reputation: 238

This has always worked well for me. It's not messy and very clean.

<a href="@Url.Action("Index", "Home")"><span>Text</span></a>

Upvotes: 7

william-kid
william-kid

Reputation: 36

Here is an uber expansion of @tvanfosson's answer. I was inspired by it and decide to make it more generic.

    public static MvcHtmlString NestedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName,
        string controllerName, object routeValues = null, object htmlAttributes = null,
        RouteValueDictionary childElements = null)
    {
        var htmlAttributesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

        if (childElements != null)
        {
            var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);

            var anchorTag = new TagBuilder("a");
            anchorTag.MergeAttribute("href",
                routeValues == null
                    ? urlHelper.Action(actionName, controllerName)
                    : urlHelper.Action(actionName, controllerName, routeValues));
            anchorTag.MergeAttributes(htmlAttributesDictionary);
            TagBuilder childTag = null;

            if (childElements != null)
            {
                foreach (var childElement in childElements)
                {
                    childTag = new TagBuilder(childElement.Key.Split('|')[0]);
                    object elementAttributes;
                    childElements.TryGetValue(childElement.Key, out elementAttributes);

                    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(elementAttributes);

                    foreach (var attribute in attributes)
                    {
                        switch (attribute.Key)
                        {
                            case "@class":
                                childTag.AddCssClass(attribute.Value.ToString());
                                break;
                            case "InnerText":
                                childTag.SetInnerText(attribute.Value.ToString());
                                break;
                            default:
                                childTag.MergeAttribute(attribute.Key, attribute.Value.ToString());
                                break;
                        }
                    }
                    childTag.ToString(TagRenderMode.SelfClosing);
                    if (childTag != null) anchorTag.InnerHtml += childTag.ToString();
                }                    
            }
            return MvcHtmlString.Create(anchorTag.ToString(TagRenderMode.Normal));
        }
        else
        {
            return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributesDictionary);
        }
    }

Upvotes: 1

DanKodi
DanKodi

Reputation: 3640

It's very simple.

If you want to have something like a glyphicon icon and then "Wish List",

<span class="glyphicon-heart"></span> @Html.ActionLink("Wish List (0)", "Index", "Home")

Upvotes: 0

Terry Kernan
Terry Kernan

Reputation: 806

I thought this might be useful when using bootstrap and some glypicons:

<a class="btn btn-primary" 
    href="<%: Url.Action("Download File", "Download", 
    new { id = msg.Id, distributorId = msg.DistributorId }) %>">
    Download
    <span class="glyphicon glyphicon-paperclip"></span>
</a>

This will show an A tag, with a link to a controller, with a nice paperclip icon on it to represent a download link, and the html output is kept clean

Upvotes: 1

David
David

Reputation: 15360

Instead of using Html.ActionLink you can render a url via Url.Action

<a href="<%= Url.Action("Index", "Home") %>"><span>Text</span></a>
<a href="@Url.Action("Index", "Home")"><span>Text</span></a>

And to do a blank url you could have

<a href="<%= Url.Action("Index", "Home") %>"></a>
<a href="@Url.Action("Index", "Home")"></a>

Upvotes: 350

Goran Obradovic
Goran Obradovic

Reputation: 9051

Here is (low and dirty) workaround in case you need to use ajax or some feature which you cannot use when making link manually (using tag):

<%= Html.ActionLink("LinkTextToken", "ActionName", "ControllerName").ToHtmlString().Replace("LinkTextToken", "Refresh <span class='large sprite refresh'></span>")%>

You can use any text instead of 'LinkTextToken', it is there only to be replaced, it is only important that it does not occur anywhere else inside actionlink.

Upvotes: 16

tvanfosson
tvanfosson

Reputation: 532465

A custom HtmlHelper extension is another option. Note: ParameterDictionary is my own type. You could substitute a RouteValueDictionary but you'd have to construct it differently.

public static string ActionLinkSpan( this HtmlHelper helper, string linkText, string actionName, string controllerName, object htmlAttributes )
{
    TagBuilder spanBuilder = new TagBuilder( "span" );
    spanBuilder.InnerHtml = linkText;

    return BuildNestedAnchor( spanBuilder.ToString(), string.Format( "/{0}/{1}", controllerName, actionName ), htmlAttributes );
}

private static string BuildNestedAnchor( string innerHtml, string url, object htmlAttributes )
{
    TagBuilder anchorBuilder = new TagBuilder( "a" );
    anchorBuilder.Attributes.Add( "href", url );
    anchorBuilder.MergeAttributes( new ParameterDictionary( htmlAttributes ) );
    anchorBuilder.InnerHtml = innerHtml;

    return anchorBuilder.ToString();
}

Upvotes: 16

Craig Stuntz
Craig Stuntz

Reputation: 126547

Just use Url.Action instead of Html.ActionLink:

<li id="home_nav"><a href="<%= Url.Action("ActionName") %>"><span>Span text</span></a></li>

Upvotes: 13

Related Questions