HTML in Html.ActionLink () einfügen, plus kein Linktext?


169

Ich habe zwei Fragen:

  1. Ich frage mich, wie ich Html.ActionLink()in einer MVC-Ansicht keinen Linktext anzeigen kann (eigentlich ist dies der Fall Site.Master).

Es gibt keine überladene Version, die keinen Linktext zulässt. Wenn ich versuche, nur ein Leerzeichen zu übergeben string, teilt mir der Compiler mit, dass eine nicht leere Zeichenfolge erforderlich ist.

Wie kann ich das beheben?

  1. Ich muss <span>Tags in das Ankertag einfügen, aber es funktioniert nicht mit Html.ActionLink();. Ich möchte die folgende Ausgabe sehen:

    Span Text

Wie kann ich Tags in das Ankertag in ASP.NET MVC einfügen?


Was wäre der Zweck / die Verwendung eines leeren Aktionslinks?
David

1
Ich verwende ein Bild-Sprite für eine Navigationsleiste, und das, was <li>Sie sehen, ist eine bestimmte Navigationsschaltfläche (mit Größe, Hintergrundposition usw., die im CSS-Stylesheet angegeben sind). Aber es muss mit etwas verknüpft sein, damit ich den Text nicht anzeigen möchte. Ich möchte, dass das Sprite das für mich tut.
MegaMatt

Antworten:


322

Anstatt Html.ActionLink zu verwenden, können Sie eine URL über Url.Action rendern

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

Und um eine leere URL zu machen, die Sie haben könnten

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

3
Ich musste <a href="@Url.Action("Index", "Home")"> <span> Text </ span> </a> verwenden. Mein Entwickler ist nicht da, um zu fragen, warum ich das tun musste Dies kann jedoch hilfreich sein, wenn jemand versucht, die obige Antwort zu verwenden und feststellt, dass sie nicht funktioniert hat.
Dave Haigh

2
@ Url.Action ist bei Verwendung der Rasiervorlage. Ich habe die Antwort aktualisiert, damit Sie beide sehen können.
David

<a href=@Url.Action("Create", "Product")><span>Create</span></a>funktioniert auch. Die Anführungszeichen sind nicht erforderlich.
David

1
Für statischen Inhalt warum nicht direkt den HTML-Code eingeben? Es scheint weniger ausführlich und einfacher
SkeetJon

Keine echte Option mehr in Asp.Net Core 2, wenn Sie Ajax verwenden möchten.
Zorkind

17

Eine benutzerdefinierte HtmlHelper-Erweiterung ist eine weitere Option. Hinweis : ParameterDictionary ist mein eigener Typ. Sie könnten ein RouteValueDictionary ersetzen, müssten es aber anders erstellen.

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();
}

14

Hier ist eine (niedrige und schmutzige) Problemumgehung für den Fall, dass Sie Ajax oder eine Funktion verwenden müssen, die Sie nicht verwenden können, wenn Sie manuell einen Link erstellen (mithilfe eines Tags):

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

Sie können jeden Text anstelle von 'LinkTextToken' verwenden. Er muss nur ersetzt werden. Es ist nur wichtig, dass er nirgendwo anders in actionlink vorkommt.


6
+1 Gute Idee. In Razor müssen Sie all das inHtml.Raw()
Carrie Kendall

Danke :) Jetzt, wo ich sehe, was wir verwendet haben, ist es mir fast peinlich, diese Dinge auf dem Server zu tun, ist eine solche Verschwendung von Serverressourcen ...
Goran Obradovic

1
Da ich @ Ajax.ActionLink verwende und nicht alle date-Attribute manuell festlegen möchte , ist dies die beste Lösung für mich. +1
Asontu

Danke, hat wie ein Zauber funktioniert, als ich auch Ajax.ActionLink verwendet habe. Es schien nichts zu verlangsamen und ich musste das gleiche Layout und Styling beibehalten.
Blacky Wolf

Ich möchte nur sagen, dass dies in .Net Core nicht funktioniert. ToHtmlString () wurde in Version 2 entfernt.
Ich bin

12

Verwenden Sie einfach Url.Actionanstelle von Html.ActionLink:

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

@CraigStunz warum sollten wir Url.Action anstelle von Html.ActionLink verwenden?
Roxy'Pro

6

Das hat bei mir immer gut funktioniert. Es ist nicht chaotisch und sehr sauber.

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


Url.Action hat keinen Konstruktor, der htmlAttributes akzeptiert. Nicht dasselbe wie ActionLink.
Barrypicker

2

Am Ende hatte ich eine benutzerdefinierte Erweiterungsmethode. Wenn Sie versuchen, HTML in ein Ankerobjekt einzufügen, kann der Linktext entweder links oder rechts vom inneren HTML stehen. Aus diesem Grund habe ich mich dafür entschieden, Parameter für linkes und rechtes inneres HTML bereitzustellen - der Linktext befindet sich in der Mitte. Sowohl linkes als auch rechtes inneres HTML sind optional.

Erweiterungsmethode 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;
    }

Anwendungsbeispiel:

Hier ist ein Anwendungsbeispiel. Für dieses Beispiel wollte ich nur das innere HTML auf der rechten Seite des Linktextes ...

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

Ergebnisse:

Dies führt zu folgendem HTML ...

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

1

Ich dachte, dies könnte nützlich sein, wenn Bootstrap und einige Glypicons verwendet werden:

<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>

Daraufhin wird ein A-Tag mit einem Link zu einem Controller und einem schönen Büroklammersymbol angezeigt, das einen Download-Link darstellt, und die HTML-Ausgabe wird sauber gehalten


1

Hier ist eine übermäßige Erweiterung der Antwort von @ tvanfosson. Ich war davon inspiriert und habe beschlossen, es allgemeiner zu gestalten.

    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);
        }
    }

1
Es ist großartig, dass Sie inspiriert wurden und die Fähigkeit dazu haben. Ich sehe mir jedoch verschachtelte foreach-Anweisungen an und möchte sie ausführen. Es ist einfach nicht für die meisten Entwickler wartbar. Wenn es ziemlich in Stein Black Box Typ Erweiterungsmethode gesetzt ist, dann möglicherweise in Ordnung, aber es hat einen Code Geruch. Für etwas, das ziemlich einfach ist, überhaupt nicht augenschonend. Vielen Dank für Ihre Bemühungen.
Tom Stickel

Ich bin sehr einverstanden mit verschachtelten for-Schleifen. Der Kürze halber ist es da. Unter dem Gesichtspunkt der Optimierung sollte die verschachtelte for-Schleife in einer eigenen privaten Methode
vorliegen

0

Es ist sehr einfach.

Wenn Sie so etwas wie ein Glyphikonsymbol und dann "Wunschliste" haben möchten,

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

0

Meine Lösung mit Bootstrap-Komponenten:

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

0

Bitte versuchen Sie es mit dem folgenden Code, der Ihnen helfen kann.

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

Einfach hinzufügen, @ Klasse und dann tatsächliche CSS-Klasse helfen mir, mein Problem zu lösen
Ahsanul
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.