web-dev-qa-db-fra.com

Insérer HTML dans Html.ActionLink (), plus aucun texte de lien?

J'ai deux questions:

  1. Je me demande comment je ne peux pas afficher de texte de lien lorsque j'utilise Html.ActionLink() dans une vue MVC (en réalité, il s'agit de Site.Master).

Aucune version surchargée n'autorisant pas le texte d'un lien, et lorsque j'essaie de transmettre uniquement un string vierge, le compilateur me dit qu'il faut une chaîne non vide.

Comment puis-je réparer cela?

  1. J'ai besoin de mettre les balises <span> dans la balise d'ancrage, mais cela ne fonctionne pas avec Html.ActionLink();. J'aimerais voir la sortie suivante:

    Texte Span

Comment insérer des balises à l'intérieur de la balise d'ancrage dans ASP.NET MVC?

161
MegaMatt

Au lieu d’utiliser Html.ActionLink, vous pouvez afficher une URL via Url.Action.

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

Et pour faire une URL vide, vous pourriez avoir

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

Une extension HtmlHelper personnalisée est une autre option. Note: ParameterDictionary est mon propre type. Vous pouvez substituer un RouteValueDictionary mais vous devez le construire différemment.

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

Voici une solution de contournement (basse et sale) au cas où vous auriez besoin d'utiliser ajax ou une fonctionnalité que vous ne pouvez pas utiliser lorsque vous créez un lien manuellement (à l'aide d'une balise):

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

Vous pouvez utiliser n’importe quel texte au lieu de 'LinkTextToken', il n’est là que pour être remplacé, il est seulement important qu’il ne se produise nulle part ailleurs dans actionlink.

12
Goran Obradovic

Utilisez simplement Url.Action au lieu de Html.ActionLink:

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

Cela a toujours bien fonctionné pour moi. Ce n'est pas sale et très propre.

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

6
dbarth

Je me suis retrouvé avec une méthode d'extension personnalisée. Il est intéressant de noter que, lorsque vous essayez de placer du HTML à l'intérieur d'un objet Anchor, le texte du lien peut être situé à gauche ou à droite du HTML interne. Pour cette raison, j'ai choisi de fournir des paramètres pour le code HTML interne gauche et droit - le texte du lien est au centre. Le HTML interne gauche et droit sont facultatifs.

Méthode d'extension 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;
    }

Exemple d'utilisation:

Voici un exemple d'utilisation. Pour cet exemple, je ne voulais que le code HTML interne à droite du texte du lien ...

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

Résultats:

cela se traduit par le code HTML suivant ...

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

Voici une extension considérable de la réponse de @ tvanfosson. Cela m'a inspiré et j'ai décidé de le rendre plus générique.

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

J'ai pensé que cela pourrait être utile lors de l'utilisation de bootstrap et de certains 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>

Cela affichera une balise A, avec un lien vers un contrôleur, avec une icône de Nice Paperclip dessus pour représenter un lien de téléchargement, et la sortie HTML restera propre.

1
Terry Kernan

Ma solution utilisant les composants bootstrap:

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

Veuillez essayer ci-dessous le code qui peut vous aider.

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

C'est très simple.

Si vous voulez avoir quelque chose comme une icône de glyphicon puis "Liste de souhaits",

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