Введення HTML всередині Html.ActionLink (), плюс відсутність тексту посилання?


169

У мене є два питання:

  1. Мені цікаво, як я можу відображати текст посилання під час використання Html.ActionLink()в режимі перегляду MVC (насправді це так Site.Master).

Не існує перевантаженої версії, яка не дозволяє текст посилання, і коли я намагаюся ввести лише порожній string, компілятор каже мені, що йому потрібна не порожня рядок.

Як я можу це виправити?

  1. Мені потрібно помістити <span>теги в тег прив’язки, але це не працює Html.ActionLink();. Я хотів би побачити такий результат:

    Проміжок тексту

Як я можу помістити теги всередині тега прив’язки до ASP.NET MVC?


Яка буде мета / використання наявності пустого посилання дії?
Девід

1
Я використовую спрайт зображень для панелі навігації, і <li>ви бачите це певна кнопка навігації (розмір, фон фону тощо, вказаний у таблиці стилів css). Але це повинно бути пов’язане з чимось, тому я не хочу відображати текст. Я хочу, щоб спрайт зробив це для мене.
MegaMatt

Відповіді:


322

Замість використання Html.ActionLink ви можете надати URL через Url.Action

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

І зробити порожній URL ви могли

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

3
Мені довелося скористатись <a href="@Url.Action("Index", "Home")"> <span> Текст </span> </a>, мій розробник не поруч, щоб запитати, чому мені довелося це робити це може бути корисним для тих, хто бажає скористатись вищезазначеною відповіддю та виявити, що це не працює.
Дейв Хей

2
@ Url.Action - це при використанні шаблону бритви. Я оновив відповідь, щоб ви могли бачити і те, і інше.
Девід

<a href=@Url.Action("Create", "Product")><span>Create</span></a>також працює. Цитати не потрібні.
Девід

1
Для статичного вмісту, чому б не ввести html безпосередньо? Це здається менш багатослівним і простішим
SkeetJon

Більше не реальна опція в Asp.Net Core 2, якщо ви хочете використовувати Ajax.
Зоркінд

17

Спеціальне розширення HtmlHelper - це ще один варіант. Примітка : ParameterDictionary - це мій власний тип. Ви можете замінити RouteValueDictionary, але вам доведеться його побудувати інакше.

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

Ось (низький і брудний) спосіб вирішення, якщо вам потрібно використовувати ajax або якусь функцію, яку ви не можете використати під час створення посилання вручну (використовуючи тег):

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

Ви можете використовувати будь-який текст замість "LinkTextToken", він є лише заміненим, важливо лише, щоб він не зустрічався ніде в середині actionlink.


6
+1 Приємна ідея. У Razor вам доведеться все це Html.Raw()
репсувати

Дякую :) Тепер, коли я бачу, що ми використовували, я майже збентежуюсь, що це робиться на сервері - це таке марнотратство серверних ресурсів ...
Goran Obradovic

1
Оскільки я використовую @ Ajax.ActionLink і мені не здається, що вручну встановити всі date-атрибути, це найкраще рішення для мене. +1
asontu

Дякую, працював як шарм, коли я також використовував Ajax.ActionLink. Це ніби нічого не сповільнювало, і я повинен був дотримуватися однакового макета та стилю.
Блеккі Вовк

Просто хочу сказати, що це не працює в .Net Core, ToHtmlString () була видалена в v2 не впевнений v1
Zorkind

12

Просто використовуйте Url.Actionзамість Html.ActionLink:

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

@CraigStunz чому ми повинні використовувати Url.Action замість Html.ActionLink?
Roxy'Pro

6

Це завжди добре працювало для мене. Це не безладно і дуже чисто.

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


Url.Action не має конструктора, який буде приймати htmlAttributes. Не те саме, що ActionLink.
barrypicker

2

Я закінчив користувальницький метод розширення. Варто зазначити, що, намагаючись розмістити HTML всередині об'єкта Якір, текст посилання може бути ліворуч або праворуч від внутрішнього HTML. З цієї причини я вирішив надати параметри для лівого та правого внутрішнього HTML - текст посилання знаходиться посередині. І лівий, і правий внутрішній HTML - необов’язкові.

Спосіб розширення 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;
    }

Приклад використання:

Ось приклад використання. Для цього прикладу я хотів лише внутрішній html у правій частині тексту посилання ...

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

Результати:

це призводить до отримання наступного HTML ...

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

1

Я подумав, що це може бути корисно при використанні завантажувального інструменту та деяких гліпіконів:

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

Це покаже тег A із посиланням на контролер, з гарним значком скріпки на ньому, щоб відобразити посилання для завантаження, а вихідний файл html підтримується чистим


1

Ось убер розширення відповіді @ tvanfosson. Я надихнувся цим і вирішив зробити це більш загальним.

    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

0

Це дуже просто.

Якщо ви хочете мати щось на зразок піктограми гліфікону, а потім "Список бажань",

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

0

Моє рішення з використанням компонентів завантажувальної програми:

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

0

Спробуйте нижче код, який може вам допомогти.

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

просто додати, @ клас, а потім фактичний клас css допоможе мені вирішити мою проблему
Ahsanul
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.