Як використовувати тире в атрибутах data-* HTML-5 в ASP.NET MVC


325

Я намагаюся використовувати атрибути даних HTML5 у своєму проекті ASP.NET MVC 1. (Я новачок C # і ASP.NET MVC.)

 <%= Html.ActionLink("« Previous", "Search",
     new { keyword = Model.Keyword, page = Model.currPage - 1},
     new { @class = "prev", data-details = "Some Details"   })%>

"Дані-дані" у наведеному вище htmlAttributes дають таку помилку:

 CS0746: Invalid anonymous type member declarator. Anonymous type members 
  must be declared with a member assignment, simple name or member access.

Він працює, коли я використовую data_details, але я думаю, що це потрібно починати з "data-" відповідно до специфікації.

Мої запитання:

  • Чи є спосіб зробити це робочим і використовувати атрибути даних HTML5 за допомогою Html.ActionLink або подібних помічників Html?
  • Чи є інший альтернативний механізм приєднання користувальницьких даних до елемента? Ці дані повинні бути оброблені пізніше JS.

5
це старе запитання із застарілою відповіддю - користувачі MVC 3 і вище повинні переглянути це питання stackoverflow.com/questions/2897733/…
ED-209

Відповіді:


115

Оновлення: MVC 3 та новіші версії мають вбудовану підтримку для цього. Нижче див. Високооцінену відповідь JohnnyO щодо рекомендованих рішень.

Я не думаю, що є безпосередні помічники для досягнення цього, але у мене є дві ідеї, щоб ви спробували:

// 1: pass dictionary instead of anonymous object
<%= Html.ActionLink( "back", "Search",
    new { keyword = Model.Keyword, page = Model.currPage - 1},
    new Dictionary<string,Object> { {"class","prev"}, {"data-details","yada"} } )%>

// 2: pass custom type decorated with descriptor attributes
public class CustomArgs
{
    public CustomArgs( string className, string dataDetails ) { ... }

    [DisplayName("class")]
    public string Class { get; set; }
    [DisplayName("data-details")]
    public string DataDetails { get; set; }
}

<%= Html.ActionLink( "back", "Search",
    new { keyword = Model.Keyword, page = Model.currPage - 1},
    new CustomArgs( "prev", "yada" ) )%>

Просто ідеї, не перевіряли.


5
Привіт. Якщо ви хочете скористатися першим підходом, просто переконайтеся, що ваш словник має тип Словник <Рядок, Об'єкт>.
Ондрей Стастний

40
Хоча це технічно працює, рекомендований спосіб (починаючи з MVC 3) - використовувати підкреслення замість дефісу (як зазначив JohnnyO).
Кертіс купує

3
Плутати весь світ із цим обраним відповіддю, поки не помітить справжню відповідь вище!
Рубенс Маріуццо

648

Ця проблема була вирішена в ASP.Net MVC 3. Вони автоматично перетворюють підкреслення в властивостях html-атрибута в тире. На цей момент їм пощастило, оскільки підкреслення не є законними в атрибутах html, тому MVC може впевнено натякати на те, що ви хочете мати тире, коли використовуєте підкреслення.

Наприклад:

@Html.TextBoxFor(vm => vm.City, new { data_bind = "foo" })

надасть це в MVC 3:

<input data-bind="foo" id="City" name="City" type="text" value="" />

Якщо ви все ще використовуєте старішу версію MVC, ви можете імітувати те, що робить MVC 3, створивши цей статичний метод, який я запозичив у вихідного коду MVC3:

public class Foo {
    public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes) {
        RouteValueDictionary result = new RouteValueDictionary();
        if (htmlAttributes != null) {
            foreach (System.ComponentModel.PropertyDescriptor property in System.ComponentModel.TypeDescriptor.GetProperties(htmlAttributes)) {
                result.Add(property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
            }
        }
        return result;
    }
}

І тоді ви можете використовувати його так:

<%: Html.TextBoxFor(vm => vm.City, Foo.AnonymousObjectToHtmlAttributes(new { data_bind = "foo" })) %>

і це надасть правильний атрибут data- *:

<input data-bind="foo" id="City" name="City" type="text" value="" />

6
Для мене це чомусь не працює. Перегляд джерела показує дані_ *. Використання MVC3. Будь-які ідеї?
Саймон Хартчер

Привіт Сімоне, ти вирішив свою проблему? Якщо ні, чи можете ви надати свій код, який викликає у вас проблему?
Джонні Ошика

Ще не пощастило WebGrid.GetHtml(htmlAttributes: new { data_some : "thing" }). : '(
Рубенс Маріуццо

+1, щоб вказати, чому підкреслення буде спрацьовувати. Мені не прийшло в голову, що підкреслення недійсні в іменах атрибутів для HTML!
Umar Farooq Khawaja

2
@RubensMariuzzo це не задіяно RouteValueDictionaryу Html.Something()методах MVC3 . Можливо, що WebGridне було оновлено так само, або ви можете перевірити версію наSystem.Web.Helpers.dll
Кіт

58

Це навіть простіше, ніж усе, що запропоновано вище. Атрибути даних у MVC, які включають тире (-), використовуються підкресленням (_).

<%= Html.ActionLink("« Previous", "Search",
 new { keyword = Model.Keyword, page = Model.currPage - 1},
 new { @class = "prev", data_details = "Some Details"   })%>

Я бачу, Джонні вже згадував про це.


12
Метод, відповідальний за це, є: HtmlHelper.AnonymousObjectToHtmlAttributes (об’єкт), якщо хтось цікавиться, чому їх власне розширення не замінить підкреслення на дефіс.
Ніккельман

1
Це справді потребує голосування, оскільки це, безумовно, найпростіша відповідь і працює чудово!
Dan Diplo

21

У mvc 4 Може бути відображено за допомогою підкреслення ("_")

Бритва:

@Html.ActionLink("Vote", "#", new { id = item.FileId, }, new { @class = "votes", data_fid = item.FileId, data_jid = item.JudgeID, })

Наданий Html

<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>

привіт, чи є спосіб відправити FID-дані на контролер, через Ajax або подати. цікаво, як використовувати дані. Наприклад, якщо я мав data-dateатрибут a , як я можу розмістити його в контролері / дії? Також те, що там є% 23
трансформатор

Так, використовуйте колекцію форм і отримайте доступ до неї за допомогою ідентифікатора чи імені, і% 23 - це #
mzonerz

4

Ви можете реалізувати це за допомогою нової функції розширення помічника Html, яка потім буде використовуватися аналогічно існуючим ActionLinks.

public static MvcHtmlString ActionLinkHtml5Data(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, object htmlDataAttributes)
{
    if (string.IsNullOrEmpty(linkText))
    {
        throw new ArgumentException(string.Empty, "linkText");
    }

    var html = new RouteValueDictionary(htmlAttributes);
    var data = new RouteValueDictionary(htmlDataAttributes);

    foreach (var attributes in data)
    {
        html.Add(string.Format("data-{0}", attributes.Key), attributes.Value);
    }

    return MvcHtmlString.Create(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null, actionName, controllerName, new RouteValueDictionary(routeValues), html));
}

І ви називаєте це так ...

<%: Html.ActionLinkHtml5Data("link display", "Action", "Controller", new { id = Model.Id }, new { @class="link" }, new { extra = "some extra info" })  %>

Симплекс :-)

редагувати

трохи більше написання тут


3

Я в кінцевому підсумку використовував звичайне гіперпосилання разом із Url.Action:

<a href='<%= Url.Action("Show", new { controller = "Browse", id = node.Id }) %>'
  data-nodeId='<%= node.Id %>'>
  <%: node.Name %>
</a>

Це гірше, але у вас є трохи більше контролю над aтегом, що іноді корисно на сильно AJAXified сайтах.

HTH


0

Мені не подобається використовувати чистий тег "a", занадто багато вводити текст. Тож я приходжу з рішенням. З огляду це виглядає

<%: Html.ActionLink(node.Name, "Show", "Browse", 
                    Dic.Route("id", node.Id), Dic.New("data-nodeId", node.Id)) %>

Впровадження класу Dic

public static class Dic
{
    public static Dictionary<string, object> New(params object[] attrs)
    {
        var res = new Dictionary<string, object>();
        for (var i = 0; i < attrs.Length; i = i + 2)
            res.Add(attrs[i].ToString(), attrs[i + 1]);
        return res;
    }

    public static RouteValueDictionary Route(params object[] attrs)
    {
        return new RouteValueDictionary(Dic.New(attrs));
    }
}

1
Безумовно, є краща назва класу ... додатково tв кінці хоча б!
hvaughan3

-2

Ви можете використовувати його так:

У Mvc:

@Html.TextBoxFor(x=>x.Id,new{@data_val_number="10"});

В Html:

<input type="text" name="Id" data_val_number="10"/>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.