Как использовать тире в атрибутах data- * HTML-5 в ASP.NET MVC

313

Я пытаюсь использовать атрибуты данных HTML5 в моем проекте ASP.NET MVC 1. (Я новичок С# и ASP.NET MVC.)

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

"Данные-данные" в приведенных выше htmlАтрибутах дают следующую ошибку:

 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.
  • 4
    это старый вопрос с устаревшим ответом - пользователи MVC 3 и выше должны просмотреть этот вопрос stackoverflow.com/questions/2897733/…
Теги:
asp.net-mvc
custom-data-attribute

8 ответов

110
Лучший ответ

Обновление: 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
    Привет. Если вы хотите использовать первый подход, просто убедитесь, что ваш словарь имеет тип Dictionary <String, Object>.
  • 40
    Хотя это технически работает, рекомендуемый способ (начиная с MVC 3) - использовать дефис вместо дефиса (как указал JohnnyO).
Показать ещё 1 комментарий
625

Эта проблема была рассмотрена в 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. Есть идеи?
  • 0
    Привет Саймон, ты решил свою проблему? Если нет, можете ли вы предоставить свой код, который вызывает у вас проблему?
Показать ещё 9 комментариев
58

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

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

Я вижу, что JohnnyO уже упоминал об этом.

  • 12
    Ответственный за это метод: HtmlHelper.AnonymousObjectToHtmlAttributes (object), если кому-то интересно, почему их пользовательское расширение не заменяет знак подчеркивания дефисом.
  • 1
    Это действительно нуждается в голосовании, поскольку это самый простой ответ и работает отлично!
13

В mvc 4 Может отображаться с помощью Underscore ( "_" )

Бритва:

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

Rendered Html

<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>
  • 0
    Привет, есть ли способ POST data-fid к контроллеру, через Ajax или отправить. интересно, как использовать данные. Например, если у меня есть data-date в атрибуте, как я могу опубликовать ее в контроллере / действии? И что там за% 23
  • 0
    Да, используйте сбор форм и получите доступ к нему с помощью идентификатора или имени, и% 23 будет #
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 сайтах.

НТН

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 в конце, по крайней мере!
-3

Вы можете использовать его следующим образом:

В Mvc:

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

В Html:

<input type="text" name="Id" data_val_number="10"/>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню